/* * Cpu initialization. Running virtual, but without MACH VM * set up. First C routine called. */ void machine_startup() { /* * Do basic VM initialization */ i386_init(); /* * Initialize the console so we can print. */ cninit(); #if MACH_KDB /* * Initialize the kernel debugger. */ ddb_init(); /* * Cause a breakpoint trap to the debugger before proceeding * any further if RB_KDB (the '-d' switch to the boot program) * was specified in the boot flags. */ if (boothowto & RB_KDB) { Debugger(); } #if 1 /* stan set to 0 [10-14-91] */ /* * XXX Until bootcube or something else allows us to dynamically * XXX provide boot options, always ask root and bootstrap names. */ boothowto |= RB_ASKNAME; boothowto |= (RB_ASKNAME << RB_SHIFT); #endif #endif MACH_KDB printf("EXPERIMENTAL "); printf(version); #if 0 { int i; db_printf("boot magic:\n"); for (i = 0; bootenv[i]; i++) { db_printf("%d %x %s\n", i, bootenv[i], bootenv[i]); } } #endif machine_slot[0].is_cpu = TRUE; machine_slot[0].running = TRUE; machine_slot[0].cpu_type = CPU_TYPE_I386; machine_slot[0].cpu_subtype = CPU_SUBTYPE_iPSC386; /* * Start the system. */ setup_main(); }
/* * Early console initialization: called early on from main, before vm init. * We want to stick to the BUG routines for now, and we'll switch to the * real console in cpu_startup(). */ void consinit() { cn_tab = NULL; cninit(); #if defined(DDB) db_machine_init(); ddb_init(); if (boothowto & RB_KDB) Debugger(); #endif }
__dead void landisk_startup(int howto, char *_esym) { u_int32_t ramsize; /* Start to determine heap area */ esym = _esym; kernend = (vaddr_t)round_page((vaddr_t)esym); boothowto = howto; ramsize = getramsize(); /* Initialize CPU ops. */ sh_cpu_init(CPU_ARCH_SH4, CPU_PRODUCT_7751R); /* Initialize early console */ consinit(); /* Load memory to UVM */ if (ramsize == 0 || ramsize > 512 * 1024 * 1024) ramsize = IOM_RAM_SIZE; physmem = atop(ramsize); kernend = atop(round_page(SH3_P1SEG_TO_PHYS(kernend))); uvm_page_physload(atop(IOM_RAM_BEGIN), atop(IOM_RAM_BEGIN + ramsize), kernend, atop(IOM_RAM_BEGIN + ramsize), 0); cpu_init_kcore_hdr(); /* need to be done before pmap_bootstrap */ /* Initialize proc0 u-area */ sh_proc0_init(); /* Initialize pmap and start to address translation */ pmap_bootstrap(); #if defined(DDB) db_machine_init(); ddb_init(); if (boothowto & RB_KDB) { Debugger(); } #endif /* Jump to main */ __asm volatile( "jmp @%0\n\t" " mov %1, sp" :: "r" (main), "r" (proc0.p_md.md_pcb->pcb_sf.sf_r7_bank)); /* NOTREACHED */ for (;;) ; }
void dreamcast_startup() { extern char edata[], end[]; paddr_t kernend; /* Clear bss */ memset(edata, 0, end - edata); /* Initialize CPU ops. */ sh_cpu_init(CPU_ARCH_SH4, CPU_PRODUCT_7750); /* Console */ consinit(); /* Load memory to UVM */ physmem = atop(IOM_RAM_SIZE); kernend = atop(round_page(SH3_P1SEG_TO_PHYS(end))); uvm_page_physload( kernend, atop(IOM_RAM_BEGIN + IOM_RAM_SIZE), kernend, atop(IOM_RAM_BEGIN + IOM_RAM_SIZE), VM_FREELIST_DEFAULT); /* Initialize proc0 u-area */ sh_proc0_init(); /* Initialize pmap and start to address translation */ pmap_bootstrap(); /* Debugger. */ #ifdef DDB ddb_init(0, NULL, NULL); #endif #if defined(KGDB) && (NSCIF > 0) if (scif_kgdb_init() == 0) { kgdb_debug_init = 1; kgdb_connect(1); } #endif /* KGDB && NSCIF > 0 */ /* Jump to main */ __asm__ __volatile__( "jmp @%0;" "mov %1, sp" :: "r"(main),"r"(proc0.p_md.md_pcb->pcb_sf.sf_r7_bank)); /* NOTREACHED */ while (1) ; }
/* * Console initialization: called early on from main, * before vm init or startup, but already running virtual. * Do enough configuration to choose and initialize a console. */ void consinit() { /* * Initialize the console before we print anything out. */ cninit(); #ifdef DDB db_machine_init(); ddb_init(); if (boothowto & RB_KDB) Debugger(); #endif }
/* * Cpu initialization. Running virtual, but without MACH VM * set up. First C routine called. */ void machine_startup() { /* * Do basic VM initialization */ i386_init(); /* * Initialize the console so we can print. */ cninit(); proberc(); #if MACH_KDB /* * Initialize the kernel debugger. */ ddb_init(); /* * Cause a breakpoint trap to the debugger before proceeding * any further if the proper option bit was specified in * the boot flags. * * XXX use -a switch to invoke kdb, since there's no * boot-program switch to turn on RB_HALT! */ if (boothowto & RB_ASKNAME) Debugger(); #endif MACH_KDB printf(version); machine_slot[0].is_cpu = TRUE; machine_slot[0].running = TRUE; machine_slot[0].cpu_type = CPU_TYPE_I386; machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386; /* * Start the system. */ setup_main(); }
/* * Early console initialization: called early on from main, before vm init. */ void consinit() { /* * Initialize the console before we print anything out. */ if (sysconsole == 0) { syscnattach(0); } else { omfb_cnattach(); ws_cnattach(); } #if defined(DDB) db_machine_init(); ddb_init(); if (boothowto & RB_KDB) Debugger(); #endif }
/* * Console initialization: called early on from main, * before vm init or startup. Do enough configuration * to choose and initialize a console. */ void consinit() { /* * Initialize the console before we print anything out. */ cninit(); #ifdef DDB { extern int end; extern int *esym; ddb_init(*(int *)&end, ((int *)&end) + 1, esym); } if (boothowto & RB_KDB) Debugger(); #endif }
vaddr_t initarm_common(vaddr_t kvm_base, vsize_t kvm_size, const struct boot_physmem *bp, size_t nbp) { struct bootmem_info * const bmi = &bootmem_info; #ifdef VERBOSE_INIT_ARM printf("nfreeblocks = %u, free_pages = %d (%#x)\n", bmi->bmi_nfreeblocks, bmi->bmi_freepages, bmi->bmi_freepages); #endif /* * Moved from cpu_startup() as data_abort_handler() references * this during uvm init. */ uvm_lwp_setuarea(&lwp0, kernelstack.pv_va); #ifdef VERBOSE_INIT_ARM printf("bootstrap done.\n"); #endif #ifdef VERBOSE_INIT_ARM printf("vectors"); #endif arm32_vector_init(systempage.pv_va, ARM_VEC_ALL); #ifdef VERBOSE_INIT_ARM printf(" %#"PRIxVADDR"\n", vector_page); #endif /* * Pages were allocated during the secondary bootstrap for the * stacks for different CPU modes. * We must now set the r13 registers in the different CPU modes to * point to these stacks. * Since the ARM stacks use STMFD etc. we must set r13 to the top end * of the stack memory. */ #ifdef VERBOSE_INIT_ARM printf("init subsystems: stacks "); #endif set_stackptr(PSR_FIQ32_MODE, fiqstack.pv_va + FIQ_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); /* * Well we should set a data abort handler. * Once things get going this will change as we will need a proper * handler. * Until then we will use a handler that just panics but tells us * why. * Initialisation of the vectors will just panic on a data abort. * This just fills in a slightly better one. */ #ifdef VERBOSE_INIT_ARM printf("vectors "); #endif data_abort_handler_address = (u_int)data_abort_handler; prefetch_abort_handler_address = (u_int)prefetch_abort_handler; undefined_handler_address = (u_int)undefinedinstruction_bounce; /* Initialise the undefined instruction handlers */ #ifdef VERBOSE_INIT_ARM printf("undefined "); #endif undefined_init(); /* Load memory into UVM. */ #ifdef VERBOSE_INIT_ARM printf("page "); #endif uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ #ifdef VERBOSE_INIT_ARM printf("pmap_physload "); #endif KASSERT(bp != NULL || nbp == 0); KASSERT(bp == NULL || nbp != 0); for (size_t i = 0; i < bmi->bmi_nfreeblocks; i++) { pv_addr_t * const pv = &bmi->bmi_freeblocks[i]; paddr_t start = atop(pv->pv_pa); const paddr_t end = start + atop(pv->pv_size); while (start < end) { int vm_freelist = VM_FREELIST_DEFAULT; paddr_t segend = end; /* * This assumes the bp list is sorted in ascending * order. */ for (size_t j = 0; j < nbp; j++) { paddr_t bp_start = bp[j].bp_start; paddr_t bp_end = bp_start + bp[j].bp_pages; if (start < bp_start) { if (segend > bp_start) { segend = bp_start; } break; } if (start < bp_end) { if (segend > bp_end) { segend = bp_end; } vm_freelist = bp[j].bp_freelist; break; } } uvm_page_physload(start, segend, start, segend, vm_freelist); start = segend; } } /* Boot strap pmap telling it where the kernel page table is */ #ifdef VERBOSE_INIT_ARM printf("pmap "); #endif pmap_bootstrap(kvm_base, kvm_base + kvm_size); #ifdef __HAVE_MEMORY_DISK__ md_root_setconf(memory_disk, sizeof memory_disk); #endif #ifdef BOOTHOWTO boothowto |= BOOTHOWTO; #endif #ifdef KGDB if (boothowto & RB_KDB) { kgdb_debug_init = 1; kgdb_connect(1); } #endif #ifdef DDB db_machine_init(); ddb_init(0, NULL, NULL); if (boothowto & RB_KDB) Debugger(); #endif #ifdef VERBOSE_INIT_ARM printf("done.\n"); #endif /* We return the new stack pointer address */ return kernelstack.pv_va + USPACE_SVC_STACK_TOP; }
void init_x86_64(paddr_t first_avail) { extern void consinit(void); extern struct extent *iomem_ex; struct region_descriptor region; struct mem_segment_descriptor *ldt_segp; int x, first16q, ist; u_int64_t seg_start, seg_end; u_int64_t seg_start1, seg_end1; cpu_init_msrs(&cpu_info_primary); proc0.p_addr = proc0paddr; cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb; x86_bus_space_init(); consinit(); /* XXX SHOULD NOT BE DONE HERE */ /* * Initailize PAGE_SIZE-dependent variables. */ uvm_setpagesize(); #if 0 uvmexp.ncolors = 2; #endif /* * Boot arguments are in a single page specified by /boot. * * We require the "new" vector form, as well as memory ranges * to be given in bytes rather than KB. * * locore copies the data into bootinfo[] for us. */ if ((bootapiver & (BAPIV_VECTOR | BAPIV_BMEMMAP)) == (BAPIV_VECTOR | BAPIV_BMEMMAP)) { if (bootinfo_size >= sizeof(bootinfo)) panic("boot args too big"); getbootinfo(bootinfo, bootinfo_size); } else panic("invalid /boot"); avail_start = PAGE_SIZE; /* BIOS leaves data in low memory */ /* and VM system doesn't work with phys 0 */ #ifdef MULTIPROCESSOR if (avail_start < MP_TRAMPOLINE + PAGE_SIZE) avail_start = MP_TRAMPOLINE + PAGE_SIZE; #endif /* * Call pmap initialization to make new kernel address space. * We must do this before loading pages into the VM system. */ pmap_bootstrap(VM_MIN_KERNEL_ADDRESS, IOM_END + trunc_page(KBTOB(biosextmem))); if (avail_start != PAGE_SIZE) pmap_prealloc_lowmem_ptps(); if (mem_cluster_cnt == 0) { /* * Allocate the physical addresses used by RAM from the iomem * extent map. This is done before the addresses are * page rounded just to make sure we get them all. */ if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem), EX_NOWAIT)) { /* XXX What should we do? */ printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM " "IOMEM EXTENT MAP!\n"); } mem_clusters[0].start = 0; mem_clusters[0].size = trunc_page(KBTOB(biosbasemem)); physmem += atop(mem_clusters[0].size); if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem), EX_NOWAIT)) { /* XXX What should we do? */ printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM " "IOMEM EXTENT MAP!\n"); } #if 0 #if NISADMA > 0 /* * Some motherboards/BIOSes remap the 384K of RAM that would * normally be covered by the ISA hole to the end of memory * so that it can be used. However, on a 16M system, this * would cause bounce buffers to be allocated and used. * This is not desirable behaviour, as more than 384K of * bounce buffers might be allocated. As a work-around, * we round memory down to the nearest 1M boundary if * we're using any isadma devices and the remapped memory * is what puts us over 16M. */ if (biosextmem > (15*1024) && biosextmem < (16*1024)) { char pbuf[9]; format_bytes(pbuf, sizeof(pbuf), biosextmem - (15*1024)); printf("Warning: ignoring %s of remapped memory\n", pbuf); biosextmem = (15*1024); } #endif #endif mem_clusters[1].start = IOM_END; mem_clusters[1].size = trunc_page(KBTOB(biosextmem)); physmem += atop(mem_clusters[1].size); mem_cluster_cnt = 2; avail_end = IOM_END + trunc_page(KBTOB(biosextmem)); } /* * If we have 16M of RAM or less, just put it all on * the default free list. Otherwise, put the first * 16M of RAM on a lower priority free list (so that * all of the ISA DMA'able memory won't be eaten up * first-off). */ if (avail_end <= (16 * 1024 * 1024)) first16q = VM_FREELIST_DEFAULT; else first16q = VM_FREELIST_FIRST16; /* Make sure the end of the space used by the kernel is rounded. */ first_avail = round_page(first_avail); kern_end = KERNBASE + first_avail; /* * Now, load the memory clusters (which have already been * rounded and truncated) into the VM system. * * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL * IS LOADED AT IOM_END (1M). */ for (x = 0; x < mem_cluster_cnt; x++) { seg_start = mem_clusters[x].start; seg_end = mem_clusters[x].start + mem_clusters[x].size; seg_start1 = 0; seg_end1 = 0; if (seg_start > 0xffffffffULL) { printf("skipping %lld bytes of memory above 4GB\n", seg_end - seg_start); continue; } if (seg_end > 0x100000000ULL) { printf("skipping %lld bytes of memory above 4GB\n", seg_end - 0x100000000ULL); seg_end = 0x100000000ULL; } /* * Skip memory before our available starting point. */ if (seg_end <= avail_start) continue; if (avail_start >= seg_start && avail_start < seg_end) { if (seg_start != 0) panic("init_x86_64: memory doesn't start at 0"); seg_start = avail_start; if (seg_start == seg_end) continue; } /* * If this segment contains the kernel, split it * in two, around the kernel. */ if (seg_start <= IOM_END && first_avail <= seg_end) { seg_start1 = first_avail; seg_end1 = seg_end; seg_end = IOM_END; } /* First hunk */ if (seg_start != seg_end) { if (seg_start <= (16 * 1024 * 1024) && first16q != VM_FREELIST_DEFAULT) { u_int64_t tmp; if (seg_end > (16 * 1024 * 1024)) tmp = (16 * 1024 * 1024); else tmp = seg_end; #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start, (unsigned long long)tmp, atop(seg_start), atop(tmp)); #endif uvm_page_physload(atop(seg_start), atop(tmp), atop(seg_start), atop(tmp), first16q); seg_start = tmp; } if (seg_start != seg_end) { #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start, (unsigned long long)seg_end, atop(seg_start), atop(seg_end)); #endif uvm_page_physload(atop(seg_start), atop(seg_end), atop(seg_start), atop(seg_end), VM_FREELIST_DEFAULT); } } /* Second hunk */ if (seg_start1 != seg_end1) { if (seg_start1 <= (16 * 1024 * 1024) && first16q != VM_FREELIST_DEFAULT) { u_int64_t tmp; if (seg_end1 > (16 * 1024 * 1024)) tmp = (16 * 1024 * 1024); else tmp = seg_end1; #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start1, (unsigned long long)tmp, atop(seg_start1), atop(tmp)); #endif uvm_page_physload(atop(seg_start1), atop(tmp), atop(seg_start1), atop(tmp), first16q); seg_start1 = tmp; } if (seg_start1 != seg_end1) { #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start1, (unsigned long long)seg_end1, atop(seg_start1), atop(seg_end1)); #endif uvm_page_physload(atop(seg_start1), atop(seg_end1), atop(seg_start1), atop(seg_end1), VM_FREELIST_DEFAULT); } } } /* * Steal memory for the message buffer (at end of core). */ { struct vm_physseg *vps = NULL; psize_t sz = round_page(MSGBUFSIZE); psize_t reqsz = sz; for (x = 0; x < vm_nphysseg; x++) { vps = &vm_physmem[x]; if (ptoa(vps->avail_end) == avail_end) break; } if (x == vm_nphysseg) panic("init_x86_64: can't find end of memory"); /* Shrink so it'll fit in the last segment. */ if ((vps->avail_end - vps->avail_start) < atop(sz)) sz = ptoa(vps->avail_end - vps->avail_start); vps->avail_end -= atop(sz); vps->end -= atop(sz); msgbuf_paddr = ptoa(vps->avail_end); /* Remove the last segment if it now has no pages. */ if (vps->start == vps->end) { for (vm_nphysseg--; x < vm_nphysseg; x++) vm_physmem[x] = vm_physmem[x + 1]; } /* Now find where the new avail_end is. */ for (avail_end = 0, x = 0; x < vm_nphysseg; x++) if (vm_physmem[x].avail_end > avail_end) avail_end = vm_physmem[x].avail_end; avail_end = ptoa(avail_end); /* Warn if the message buffer had to be shrunk. */ if (sz != reqsz) printf("WARNING: %ld bytes not available for msgbuf " "in last cluster (%ld used)\n", reqsz, sz); } /* * XXXfvdl todo: acpi wakeup code. */ pmap_growkernel(VM_MIN_KERNEL_ADDRESS + 32 * 1024 * 1024); pmap_kenter_pa(idt_vaddr, idt_paddr, VM_PROT_READ|VM_PROT_WRITE); pmap_kenter_pa(idt_vaddr + PAGE_SIZE, idt_paddr + PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE); pmap_kenter_pa(lo32_vaddr, lo32_paddr, VM_PROT_READ|VM_PROT_WRITE); idt = (struct gate_descriptor *)idt_vaddr; gdtstore = (char *)(idt + NIDT); ldtstore = gdtstore + DYNSEL_START; /* make gdt gates and memory segments */ set_mem_segment(GDT_ADDR_MEM(gdtstore, GCODE_SEL), 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 0, 1); set_mem_segment(GDT_ADDR_MEM(gdtstore, GDATA_SEL), 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 0, 1); set_sys_segment(GDT_ADDR_SYS(gdtstore, GLDT_SEL), ldtstore, LDT_SIZE - 1, SDT_SYSLDT, SEL_KPL, 0); set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 0, 1); set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 0, 1); /* make ldt gates and memory segments */ setgate((struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL), &IDTVEC(oosyscall), 0, SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); *(struct mem_segment_descriptor *)(ldtstore + LUCODE_SEL) = *GDT_ADDR_MEM(gdtstore, GUCODE_SEL); *(struct mem_segment_descriptor *)(ldtstore + LUDATA_SEL) = *GDT_ADDR_MEM(gdtstore, GUDATA_SEL); /* * 32 bit GDT entries. */ set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE32_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 1, 0); set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA32_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0); /* * 32 bit LDT entries. */ ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUCODE32_SEL); set_mem_segment(ldt_segp, 0, atop(VM_MAXUSER_ADDRESS32) - 1, SDT_MEMERA, SEL_UPL, 1, 1, 0); ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUDATA32_SEL); set_mem_segment(ldt_segp, 0, atop(VM_MAXUSER_ADDRESS32) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0); /* * Other entries. */ memcpy((struct gate_descriptor *)(ldtstore + LSOL26CALLS_SEL), (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL), sizeof (struct gate_descriptor)); memcpy((struct gate_descriptor *)(ldtstore + LBSDICALLS_SEL), (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL), sizeof (struct gate_descriptor)); /* exceptions */ for (x = 0; x < 32; x++) { ist = (x == 8) ? 1 : 0; setgate(&idt[x], IDTVEC(exceptions)[x], ist, SDT_SYS386IGT, (x == 3 || x == 4) ? SEL_UPL : SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); idt_allocmap[x] = 1; } /* new-style interrupt gate for syscalls */ setgate(&idt[128], &IDTVEC(osyscall), 0, SDT_SYS386IGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); idt_allocmap[128] = 1; setregion(®ion, gdtstore, DYNSEL_START - 1); lgdt(®ion); cpu_init_idt(); #ifdef DDB db_machine_init(); ddb_init(); if (boothowto & RB_KDB) Debugger(); #endif #ifdef KGDB kgdb_port_init(); if (boothowto & RB_KDB) { kgdb_debug_init = 1; kgdb_connect(1); } #endif intr_default_setup(); softintr_init(); splraise(IPL_IPI); enable_intr(); /* Make sure maxproc is sane */ if (maxproc > cpu_maxproc()) maxproc = cpu_maxproc(); }
/* * u_int initarm(...) * * Initial entry point on startup. This gets called before main() is * entered. * It should be responsible for setting up everything that must be * in place when main is called. * This includes * Taking a copy of the boot configuration structure. * Initialising the physical console so characters can be printed. * Setting up page tables for the kernel * Relocating the kernel to the bottom of physical memory */ u_int initarm(void *arg) { extern vaddr_t xscale_cache_clean_addr; int loop; int loop1; u_int l1pagetable; #ifdef DIAGNOSTIC extern vsize_t xscale_minidata_clean_size; /* used in KASSERT */ #endif /* Register devmap for devices we mapped in start */ pmap_devmap_register(viper_devmap); /* start 32.768 kHz OSC */ ioreg_write(VIPER_CLKMAN_VBASE + 0x08, 2); /* Get ready for splfoo() */ pxa2x0_intr_bootstrap(VIPER_INTCTL_VBASE); /* * Heads up ... Setup the CPU / MMU / TLB functions */ if (set_cpufuncs()) panic("cpu not recognized!"); #if 0 /* Calibrate the delay loop. */ #endif /* setup GPIO for BTUART, in case bootloader doesn't take care of it */ pxa2x0_gpio_bootstrap(VIPER_GPIO_VBASE); pxa2x0_gpio_config(viper_gpioconf); /* turn on clock to UART block. XXX: this should not be done here. */ ioreg_write(VIPER_CLKMAN_VBASE+CLKMAN_CKEN, CKEN_FFUART|CKEN_BTUART | ioreg_read(VIPER_CLKMAN_VBASE+CLKMAN_CKEN)); consinit(); #ifdef KGDB kgdb_port_init(); #endif /* Talk to the user */ printf("\nNetBSD/evbarm (viper) booting ...\n"); #if 0 /* * Examine the boot args string for options we need to know about * now. */ process_kernel_args((char *)nwbootinfo.bt_args); #endif printf("initarm: Configuring system ...\n"); /* Fake bootconfig structure for the benefit of pmap.c */ /* XXX must make the memory description h/w independent */ bootconfig.dramblocks = 1; bootconfig.dram[0].address = MEMSTART; bootconfig.dram[0].pages = MEMSIZE / PAGE_SIZE; /* * Set up the variables that define the availablilty of * physical memory. For now, we're going to set * physical_freestart to 0xa0200000 (where the kernel * was loaded), and allocate the memory we need downwards. * If we get too close to the page tables that RedBoot * set up, we will panic. We will update physical_freestart * and physical_freeend later to reflect what pmap_bootstrap() * wants to see. * * XXX pmap_bootstrap() needs an enema. * (now that would be truly hardcore XXX) */ physical_start = bootconfig.dram[0].address; physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE); physical_freestart = 0xa0009000UL; physical_freeend = 0xa0200000UL; physmem = (physical_end - physical_start) / PAGE_SIZE; #ifdef VERBOSE_INIT_ARM /* Tell the user about the memory */ printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem, physical_start, physical_end - 1); #endif /* * Okay, the kernel starts 2MB in from the bottom of physical * memory. We are going to allocate our bootstrap pages downwards * from there. * * We need to allocate some fixed page tables to get the kernel * going. We allocate one page directory and a number of page * tables and store the physical addresses in the kernel_pt_table * array. * * The kernel page directory must be on a 16K boundary. The page * tables must be on 4K boundaries. What we do is allocate the * page directory on the first 16K boundary that we encounter, and * the page tables on 4K boundaries otherwise. Since we allocate * at least 3 L2 page tables, we are guaranteed to encounter at * least one 16K aligned region. */ #ifdef VERBOSE_INIT_ARM printf("Allocating page tables\n"); #endif free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; #ifdef VERBOSE_INIT_ARM printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n", physical_freestart, free_pages, free_pages); #endif /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; #define alloc_pages(var, np) \ physical_freeend -= ((np) * PAGE_SIZE); \ if (physical_freeend < physical_freestart) \ panic("initarm: out of memory"); \ (var) = physical_freeend; \ free_pages -= (np); \ memset((char *)(var), 0, ((np) * PAGE_SIZE)); loop1 = 0; for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { /* Are we 16KB aligned for an L1 ? */ if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0 && kernel_l1pt.pv_pa == 0) { valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); } else { valloc_pages(kernel_pt_table[loop1], L2_TABLE_SIZE / PAGE_SIZE); ++loop1; } } /* This should never be able to happen but better confirm that. */ if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) panic("initarm: Failed to align the kernel page directory"); /* * Allocate a page for the system page mapped to V0x00000000 * This page will just contain the system vectors and can be * shared by all processes. */ alloc_pages(systempage.pv_pa, 1); /* Allocate stacks for all modes */ valloc_pages(irqstack, IRQ_STACK_SIZE); valloc_pages(abtstack, ABT_STACK_SIZE); valloc_pages(undstack, UND_STACK_SIZE); valloc_pages(kernelstack, UPAGES); /* Allocate enough pages for cleaning the Mini-Data cache. */ KASSERT(xscale_minidata_clean_size <= PAGE_SIZE); valloc_pages(minidataclean, 1); #ifdef VERBOSE_INIT_ARM printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, irqstack.pv_va); printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, abtstack.pv_va); printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, undstack.pv_va); printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, kernelstack.pv_va); #endif /* * XXX Defer this to later so that we can reclaim the memory * XXX used by the RedBoot page tables. */ alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); /* * Ok we have allocated physical pages for the primary kernel * page tables */ #ifdef VERBOSE_INIT_ARM printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa); #endif /* * Now we start construction of the L1 page table * We start by mapping the L2 page tables into the L1. * This means that we can replace L1 mappings later on if necessary */ l1pagetable = kernel_l1pt.pv_pa; /* Map the L2 pages tables in the L1 page table */ pmap_link_l2pt(l1pagetable, 0x00000000, &kernel_pt_table[KERNEL_PT_SYS]); for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++) pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000, &kernel_pt_table[KERNEL_PT_KERNEL + loop]); for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++) pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, &kernel_pt_table[KERNEL_PT_VMDATA + loop]); /* update the top of the kernel VM */ pmap_curmaxkvaddr = KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); #ifdef VERBOSE_INIT_ARM printf("Mapping kernel\n"); #endif /* Now we fill in the L2 pagetable for the kernel static code/data */ { extern char etext[], _end[]; size_t textsize = (uintptr_t) etext - KERNEL_TEXT_BASE; size_t totalsize = (uintptr_t) _end - KERNEL_TEXT_BASE; u_int logical; textsize = (textsize + PGOFSET) & ~PGOFSET; totalsize = (totalsize + PGOFSET) & ~PGOFSET; logical = 0x00200000; /* offset of kernel in RAM */ logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, physical_start + logical, textsize, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, physical_start + logical, totalsize - textsize, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); } #ifdef VERBOSE_INIT_ARM printf("Constructing L2 page tables\n"); #endif /* Map the stack pages */ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE); for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); } /* Map the Mini-Data cache clean area. */ xscale_setup_minidata(l1pagetable, minidataclean.pv_va, minidataclean.pv_pa); /* Map the vector page. */ #if 1 /* MULTI-ICE requires that page 0 is NC/NB so that it can download the * cache-clean code there. */ pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa, VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE); #else pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); #endif /* * map integrated peripherals at same address in l1pagetable * so that we can continue to use console. */ pmap_devmap_bootstrap(l1pagetable, viper_devmap); /* * Give the XScale global cache clean code an appropriately * sized chunk of unmapped VA space starting at 0xff000000 * (our device mappings end before this address). */ xscale_cache_clean_addr = 0xff000000U; /* * Now we have the real page tables in place so we can switch to them. * Once this is done we will be running with the REAL kernel page * tables. */ /* * Update the physical_freestart/physical_freeend/free_pages * variables. */ { extern char _end[]; physical_freestart = physical_start + (((((uintptr_t) _end) + PGOFSET) & ~PGOFSET) - KERNEL_BASE); physical_freeend = physical_end; free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; } /* Switch tables */ #ifdef VERBOSE_INIT_ARM printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", physical_freestart, free_pages, free_pages); printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa); #endif cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); /* * Moved from cpu_startup() as data_abort_handler() references * this during uvm init */ proc0paddr = (struct user *)kernelstack.pv_va; lwp0.l_addr = proc0paddr; #ifdef VERBOSE_INIT_ARM printf("bootstrap done.\n"); #endif arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL); /* * Pages were allocated during the secondary bootstrap for the * stacks for different CPU modes. * We must now set the r13 registers in the different CPU modes to * point to these stacks. * Since the ARM stacks use STMFD etc. we must set r13 to the top end * of the stack memory. */ printf("init subsystems: stacks "); set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); /* * Well we should set a data abort handler. * Once things get going this will change as we will need a proper * handler. * Until then we will use a handler that just panics but tells us * why. * Initialisation of the vectors will just panic on a data abort. * This just fills in a slightly better one. */ printf("vectors "); data_abort_handler_address = (u_int)data_abort_handler; prefetch_abort_handler_address = (u_int)prefetch_abort_handler; undefined_handler_address = (u_int)undefinedinstruction_bounce; /* Initialise the undefined instruction handlers */ printf("undefined "); undefined_init(); /* Load memory into UVM. */ printf("page "); uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ uvm_page_physload(atop(physical_freestart), atop(physical_freeend), atop(physical_freestart), atop(physical_freeend), VM_FREELIST_DEFAULT); /* Boot strap pmap telling it where the kernel page table is */ printf("pmap "); pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); #ifdef __HAVE_MEMORY_DISK__ md_root_setconf(memory_disk, sizeof memory_disk); #endif #ifdef KGDB if (boothowto & RB_KDB) { kgdb_debug_init = 1; kgdb_connect(1); } #endif #ifdef DDB db_machine_init(); /* Firmware doesn't load symbols. */ ddb_init(0, NULL, NULL); if (boothowto & RB_KDB) Debugger(); #endif /* We return the new stack pointer address */ return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); }
/* * u_int initarm(...) * * Initial entry point on startup. This gets called before main() is * entered. * It should be responsible for setting up everything that must be * in place when main is called. * This includes * Taking a copy of the boot configuration structure. * Initialising the physical console so characters can be printed. * Setting up page tables for the kernel * Relocating the kernel to the bottom of physical memory */ u_int initarm(void *arg) { /* * When we enter here, we are using a temporary first level * translation table with section entries in it to cover the TIPB * peripherals and SDRAM. The temporary first level translation table * is at the end of SDRAM. */ /* Heads up ... Setup the CPU / MMU / TLB functions. */ if (set_cpufuncs()) panic("cpu not recognized!"); init_clocks(); /* The console is going to try to map things. Give pmap a devmap. */ pmap_devmap_register(devmap); consinit(); #ifdef KGDB kgdb_port_init(); #endif #ifdef VERBOSE_INIT_ARM /* Talk to the user */ printf("\nNetBSD/evbarm (OSK5912) booting ...\n"); #endif #ifdef BOOT_ARGS char mi_bootargs[] = BOOT_ARGS; parse_mi_bootargs(mi_bootargs); #endif #ifdef VERBOSE_INIT_ARM printf("initarm: Configuring system ...\n"); #endif /* * Set up the variables that define the availability of physical * memory. */ physical_start = KERNEL_BASE_PHYS; physical_end = physical_start + MEMSIZE_BYTES; physmem = MEMSIZE_BYTES / PAGE_SIZE; /* Fake bootconfig structure for the benefit of pmap.c. */ bootconfig.dramblocks = 1; bootconfig.dram[0].address = physical_start; bootconfig.dram[0].pages = physmem; /* * Our kernel is at the beginning of memory, so set our free space to * all the memory after the kernel. */ physical_freestart = KERN_VTOPHYS(round_page((vaddr_t) _end)); physical_freeend = physical_end; free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; /* * This is going to do all the hard work of setting up the first and * and second level page tables. Pages of memory will be allocated * and mapped for other structures that are required for system * operation. When it returns, physical_freestart and free_pages will * have been updated to reflect the allocations that were made. In * addition, kernel_l1pt, kernel_pt_table[], systempage, irqstack, * abtstack, undstack, kernelstack, msgbufphys will be set to point to * the memory that was allocated for them. */ setup_real_page_tables(); /* * Moved from cpu_startup() as data_abort_handler() references * this during uvm init. */ proc0paddr = (struct user *)kernelstack.pv_va; lwp0.l_addr = proc0paddr; #ifdef VERBOSE_INIT_ARM printf("bootstrap done.\n"); #endif arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL); /* * Pages were allocated during the secondary bootstrap for the * stacks for different CPU modes. * We must now set the r13 registers in the different CPU modes to * point to these stacks. * Since the ARM stacks use STMFD etc. we must set r13 to the top end * of the stack memory. */ #ifdef VERBOSE_INIT_ARM printf("init subsystems: stacks "); #endif set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); /* * Well we should set a data abort handler. * Once things get going this will change as we will need a proper * handler. * Until then we will use a handler that just panics but tells us * why. * Initialisation of the vectors will just panic on a data abort. * This just fills in a slightly better one. */ #ifdef VERBOSE_INIT_ARM printf("vectors "); #endif data_abort_handler_address = (u_int)data_abort_handler; prefetch_abort_handler_address = (u_int)prefetch_abort_handler; undefined_handler_address = (u_int)undefinedinstruction_bounce; /* Initialise the undefined instruction handlers */ #ifdef VERBOSE_INIT_ARM printf("undefined "); #endif undefined_init(); /* Load memory into UVM. */ #ifdef VERBOSE_INIT_ARM printf("page "); #endif uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ uvm_page_physload(atop(physical_freestart), atop(physical_freeend), atop(physical_freestart), atop(physical_freeend), VM_FREELIST_DEFAULT); /* Boot strap pmap telling it where the kernel page table is */ #ifdef VERBOSE_INIT_ARM printf("pmap "); #endif pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); #ifdef VERBOSE_INIT_ARM printf("done.\n"); #endif #ifdef KGDB if (boothowto & RB_KDB) { kgdb_debug_init = 1; kgdb_connect(1); } #endif #ifdef DDB db_machine_init(); /* Firmware doesn't load symbols. */ ddb_init(0, NULL, NULL); if (boothowto & RB_KDB) Debugger(); #endif /* We return the new stack pointer address */ return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); }
/* * Do all the stuff that locore normally does before calling main(). */ void mach_init(int argc, char **argv, yamon_env_var *envp, u_long memsize) { struct malta_config *mcp = &malta_configuration; bus_space_handle_t sh; caddr_t kernend, v; u_long first, last; vsize_t size; char *cp; int i, howto; uint8_t *brkres = (uint8_t *)MIPS_PHYS_TO_KSEG1(MALTA_BRKRES); extern char edata[], end[]; *brkres = 0; /* Disable BREAK==reset on console */ /* Get the propaganda in early! */ led_display_str("NetBSD"); /* * Clear the BSS segment. */ kernend = (caddr_t)mips_round_page(end); memset(edata, 0, kernend - edata); /* save the yamon environment pointer */ yamon_envp = envp; /* Use YAMON callbacks for early console I/O */ cn_tab = &yamon_promcd; /* * Set up the exception vectors and cpu-specific function * vectors early on. We need the wbflush() vector set up * before comcnattach() is called (or at least before the * first printf() after that is called). * Also clears the I+D caches. */ mips_vector_init(); uvm_setpagesize(); physmem = btoc(memsize); gt_pci_init(&mcp->mc_pc, &mcp->mc_gt); malta_bus_io_init(&mcp->mc_iot, mcp); malta_bus_mem_init(&mcp->mc_memt, mcp); malta_dma_init(mcp); /* * Calibrate the timer, delay() relies on this. */ bus_space_map(&mcp->mc_iot, MALTA_RTCADR, 2, 0, &sh); malta_cal_timer(&mcp->mc_iot, sh); bus_space_unmap(&mcp->mc_iot, sh, 2); #if NCOM > 0 /* * Delay to allow firmware putchars to complete. * FIFO depth * character time. * character time = (1000000 / (defaultrate / 10)) */ delay(160000000 / comcnrate); if (comcnattach(&mcp->mc_iot, MALTA_UART0ADR, comcnrate, COM_FREQ, (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0) panic("malta: unable to initialize serial console"); #else panic("malta: not configured to use serial console"); #endif /* NCOM > 0 */ consinit(); mem_clusters[0].start = 0; mem_clusters[0].size = ctob(physmem); mem_cluster_cnt = 1; /* * XXX: check argv[0] - do something if "gdb"??? */ /* * Look at arguments passed to us and compute boothowto. */ boothowto = RB_AUTOBOOT; for (i = 1; i < argc; i++) { for (cp = argv[i]; *cp; cp++) { /* Ignore superfluous '-', if there is one */ if (*cp == '-') continue; howto = 0; BOOT_FLAG(*cp, howto); if (! howto) printf("bootflag '%c' not recognised\n", *cp); else boothowto |= howto; } } /* * Load the rest of the available pages into the VM system. */ 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); /* * Initialize error message buffer (at end of core). */ mips_init_msgbuf(); /* * Compute the size of system data structures. pmap_bootstrap() * needs some of this information. */ size = (vsize_t)allocsys(NULL, NULL); pmap_bootstrap(); /* * Allocate space for proc0's USPACE. */ v = (caddr_t)uvm_pageboot_alloc(USPACE); proc0.p_addr = proc0paddr = (struct user *)v; proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; curpcb = &proc0.p_addr->u_pcb; curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ /* * Allocate space for system data structures. These data structures * are allocated here instead of cpu_startup() because physical * memory is directly addressable. We don't have to map these into * virtual address space. */ v = (caddr_t)uvm_pageboot_alloc(size); if ((allocsys(v, NULL) - v) != size) panic("mach_init: table size inconsistency"); /* * Initialize debuggers, and break into them, if appropriate. */ #ifdef DDB ddb_init(0, 0, 0); #endif if (boothowto & RB_KDB) #if defined(DDB) Debugger(); #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() { 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(); }
static int __init octonet_probe(struct platform_device *pdev) { struct ddb *dev; struct resource *regs; int irq; dev = vzalloc(sizeof(struct ddb)); if (!dev) return -ENOMEM; platform_set_drvdata(pdev, dev); dev->dev = &pdev->dev; dev->pfdev = pdev; mutex_init(&dev->mutex); regs = platform_get_resource(dev->pfdev, IORESOURCE_MEM, 0); if (!regs) return -ENXIO; dev->regs_len = (regs->end - regs->start) + 1; dev_info(dev->dev, "regs_start=%08x regs_len=%08x\n", (u32) regs->start, (u32) dev->regs_len); dev->regs = ioremap(regs->start, dev->regs_len); if (!dev->regs) { dev_err(dev->dev, "ioremap failed\n"); return -ENOMEM; } dev->link[0].ids.hwid = ddbreadl(dev, 0); dev->link[0].ids.regmapid = ddbreadl(dev, 4); dev->link[0].ids.devid = ddbreadl(dev, 8); dev->link[0].ids.mac = ddbreadl(dev, 12); dev->link[0].ids.vendor = dev->link[0].ids.devid & 0xffff; dev->link[0].ids.device = dev->link[0].ids.devid >> 16; dev->link[0].ids.subvendor = dev->link[0].ids.devid & 0xffff; dev->link[0].ids.subdevice = dev->link[0].ids.devid >> 16; dev->link[0].dev = dev; if (dev->link[0].ids.devid == 0x0300dd01) dev->link[0].info = &ddb_octonet; else if (dev->link[0].ids.devid == 0x0301dd01) dev->link[0].info = &ddb_octonet_jse; else if (dev->link[0].ids.devid == 0x0307dd01) dev->link[0].info = &ddb_octonet_gtl; else dev->link[0].info = &ddb_octonet_tbd; pr_info("HW %08x REGMAP %08x\n", dev->link[0].ids.hwid, dev->link[0].ids.regmapid); pr_info("MAC %08x DEVID %08x\n", dev->link[0].ids.mac, dev->link[0].ids.devid); ddbwritel(dev, 0, ETHER_CONTROL); ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE); ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS); ddb_reset_ios(dev); irq = platform_get_irq(dev->pfdev, 0); if (irq < 0) goto fail; if (request_irq(irq, irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "octonet-dvb", (void *) dev) < 0) goto fail; ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE); if (ddb_init(dev) == 0) return 0; fail: dev_err(dev->dev, "fail\n"); ddbwritel(dev, 0, ETHER_CONTROL); ddbwritel(dev, 0, INTERRUPT_ENABLE); octonet_unmap(dev); platform_set_drvdata(pdev, 0); return -1; }
/* * u_int initarm(...) * * Initial entry point on startup. This gets called before main() is * entered. * It should be responsible for setting up everything that must be * in place when main is called. * This includes * Taking a copy of the boot configuration structure. * Initialising the physical console so characters can be printed. * Setting up page tables for the kernel * Relocating the kernel to the bottom of physical memory */ u_int initarm(void *arg0, void *arg1, void *arg2) { extern vaddr_t xscale_cache_clean_addr; extern cpu_kcore_hdr_t cpu_kcore_hdr; int loop; int loop1; u_int l1pagetable; pv_addr_t kernel_l1pt; paddr_t memstart; psize_t memsize; extern u_int32_t esym; /* &_end if no symbols are loaded */ #ifdef DIAGNOSTIC extern vsize_t xscale_minidata_clean_size; /* used in KASSERT */ #endif /* setup a serial console for very early boot */ consinit(); /* * Heads up ... Setup the CPU / MMU / TLB functions */ if (set_cpufuncs()) panic("cpu not recognized!"); /* * Examine the boot args string for options we need to know about * now. */ /* XXX should really be done after setting up the console, but we * XXX need to parse the console selection flags right now. */ process_kernel_args((char *)0xa0200000 - MAX_BOOT_STRING - 1); /* Calibrate the delay loop. */ #if 1 i80321_calibrate_delay(); #endif /* Talk to the user */ printf("\nOpenBSD/armish booting ...\n"); /* * Reset the secondary PCI bus. RedBoot doesn't stop devices * on the PCI bus before handing us control, so we have to * do this. * * XXX This is arguably a bug in RedBoot, and doing this reset * XXX could be problematic in the future if we encounter an * XXX application where the PPB in the i80312 is used as a * XXX PPB. */ //#define VERBOSE_INIT_ARM /* * Fetch the SDRAM start/size from the i80312 SDRAM configuration * registers. */ i80321_sdram_bounds(&obio_bs_tag, VERDE_PMMR_BASE + VERDE_MCU_BASE, &memstart, &memsize); #define DEBUG #ifdef DEBUG printf("initarm: Configuring system ...\n"); #endif /* Fake bootconfig structure for the benefit of pmap.c */ /* XXX must make the memory description h/w independant */ bootconfig.dramblocks = 1; bootconfig.dram[0].address = memstart; bootconfig.dram[0].pages = memsize / PAGE_SIZE; /* * Set up the variables that define the availablilty of * physical memory. For now, we're going to set * physical_freestart to 0xa0200000 (where the kernel * was loaded), and allocate the memory we need downwards. * If we get too close to the page tables that RedBoot * set up, we will panic. We will update physical_freestart * and physical_freeend later to reflect what pmap_bootstrap() * wants to see. * * XXX pmap_bootstrap() needs an enema. */ physical_start = bootconfig.dram[0].address; physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE); physical_freestart = 0xa0009000UL; physical_freeend = 0xa0200000UL; physmem = (physical_end - physical_start) / PAGE_SIZE; #ifdef DEBUG /* Tell the user about the memory */ printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem, physical_start, physical_end - 1); #endif /* * Okay, the kernel starts 2MB in from the bottom of physical * memory. We are going to allocate our bootstrap pages downwards * from there. * * We need to allocate some fixed page tables to get the kernel * going. We allocate one page directory and a number of page * tables and store the physical addresses in the kernel_pt_table * array. * * The kernel page directory must be on a 16K boundary. The page * tables must be on 4K boundaries. What we do is allocate the * page directory on the first 16K boundary that we encounter, and * the page tables on 4K boundaries otherwise. Since we allocate * at least 3 L2 page tables, we are guaranteed to encounter at * least one 16K aligned region. */ #ifdef VERBOSE_INIT_ARM printf("Allocating page tables\n"); #endif free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; #ifdef VERBOSE_INIT_ARM printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n", physical_freestart, free_pages, free_pages); #endif /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; #define alloc_pages(var, np) \ physical_freeend -= ((np) * PAGE_SIZE); \ if (physical_freeend < physical_freestart) \ panic("initarm: out of memory"); \ (var) = physical_freeend; \ free_pages -= (np); \ memset((char *)(var), 0, ((np) * PAGE_SIZE)); loop1 = 0; kernel_l1pt.pv_pa = 0; for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { /* Are we 16KB aligned for an L1 ? */ if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0 && kernel_l1pt.pv_pa == 0) { valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); } else { valloc_pages(kernel_pt_table[loop1], L2_TABLE_SIZE / PAGE_SIZE); ++loop1; } } /* This should never be able to happen but better confirm that. */ if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) panic("initarm: Failed to align the kernel page directory"); /* * Allocate a page for the system page mapped to V0x00000000 * This page will just contain the system vectors and can be * shared by all processes. */ alloc_pages(systempage.pv_pa, 1); /* Allocate stacks for all modes */ valloc_pages(irqstack, IRQ_STACK_SIZE); valloc_pages(abtstack, ABT_STACK_SIZE); valloc_pages(undstack, UND_STACK_SIZE); valloc_pages(kernelstack, UPAGES); /* Allocate enough pages for cleaning the Mini-Data cache. */ KASSERT(xscale_minidata_clean_size <= PAGE_SIZE); valloc_pages(minidataclean, 1); #ifdef VERBOSE_INIT_ARM printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, irqstack.pv_va); printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, abtstack.pv_va); printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, undstack.pv_va); printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, kernelstack.pv_va); #endif /* * XXX Defer this to later so that we can reclaim the memory * XXX used by the RedBoot page tables. */ alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); /* * Ok we have allocated physical pages for the primary kernel * page tables */ #ifdef VERBOSE_INIT_ARM printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa); #endif /* * Now we start construction of the L1 page table * We start by mapping the L2 page tables into the L1. * This means that we can replace L1 mappings later on if necessary */ l1pagetable = kernel_l1pt.pv_pa; #ifdef HIGH_VECT /* Map the L2 pages tables in the L1 page table */ pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00400000 - 1), &kernel_pt_table[KERNEL_PT_SYS]); #else /* Map the L2 pages tables in the L1 page table */ pmap_link_l2pt(l1pagetable, 0x00000000, &kernel_pt_table[KERNEL_PT_SYS]); #endif for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++) pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000, &kernel_pt_table[KERNEL_PT_KERNEL + loop]); for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++) pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, &kernel_pt_table[KERNEL_PT_VMDATA + loop]); #if 0 pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE, &kernel_pt_table[KERNEL_PT_IOPXS]); #endif /* update the top of the kernel VM */ pmap_curmaxkvaddr = KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); #ifdef VERBOSE_INIT_ARM printf("Mapping kernel\n"); #endif /* Now we fill in the L2 pagetable for the kernel static code/data * and the symbol table. */ { extern char etext[]; #ifdef VERBOSE_INIT_ARM extern char _end[]; #endif size_t textsize = (u_int32_t) etext - KERNEL_TEXT_BASE; size_t totalsize = esym - KERNEL_TEXT_BASE; u_int logical; #ifdef VERBOSE_INIT_ARM printf("kernelsize text %x total %x end %xesym %x\n", textsize, totalsize, _end, esym); #endif textsize = round_page(textsize); totalsize = round_page(totalsize); logical = 0x00200000; /* offset of kernel in RAM */ /* Update dump information */ cpu_kcore_hdr.kernelbase = KERNEL_BASE; cpu_kcore_hdr.kerneloffs = logical; cpu_kcore_hdr.staticsize = totalsize; logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, physical_start + logical, textsize, PROT_READ | PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, physical_start + logical, totalsize - textsize, PROT_READ | PROT_WRITE, PTE_CACHE); } #ifdef VERBOSE_INIT_ARM printf("Constructing L2 page tables\n"); #endif /* Map the stack pages */ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, IRQ_STACK_SIZE * PAGE_SIZE, PROT_READ | PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, ABT_STACK_SIZE * PAGE_SIZE, PROT_READ | PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, UND_STACK_SIZE * PAGE_SIZE, PROT_READ | PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, UPAGES * PAGE_SIZE, PROT_READ | PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, L1_TABLE_SIZE, PROT_READ | PROT_WRITE, PTE_PAGETABLE); for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, PROT_READ | PROT_WRITE, PTE_PAGETABLE); } /* Map the Mini-Data cache clean area. */ xscale_setup_minidata(l1pagetable, minidataclean.pv_va, minidataclean.pv_pa); /* Map the vector page. */ #ifdef HIGH_VECT pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, PROT_READ | PROT_WRITE, PTE_CACHE); #else pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa, PROT_READ | PROT_WRITE, PTE_CACHE); #endif pmap_devmap_bootstrap(l1pagetable, iq80321_devmap); /* * Give the XScale global cache clean code an appropriately * sized chunk of unmapped VA space starting at 0xff000000 * (our device mappings end before this address). */ xscale_cache_clean_addr = 0xff000000U; /* * Now we have the real page tables in place so we can switch to them. * Once this is done we will be running with the REAL kernel page * tables. */ /* * Update the physical_freestart/physical_freeend/free_pages * variables. */ { physical_freestart = physical_start - KERNEL_BASE + round_page(esym); physical_freeend = physical_end; free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; } #ifdef VERBOSE_INIT_ARM printf("physical_freestart %x end %x\n", physical_freestart, physical_freeend); #endif /* be a client to all domains */ cpu_domains(0x55555555); /* Switch tables */ #ifdef VERBOSE_INIT_ARM printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", physical_freestart, free_pages, free_pages); printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa); #endif cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); /* * Moved from cpu_startup() as data_abort_handler() references * this during uvm init */ proc0paddr = (struct user *)kernelstack.pv_va; proc0.p_addr = proc0paddr; #ifdef VERBOSE_INIT_ARM printf("bootstrap done.\n"); #endif #ifdef HIGH_VECT arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); #else arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL); #endif /* * Pages were allocated during the secondary bootstrap for the * stacks for different CPU modes. * We must now set the r13 registers in the different CPU modes to * point to these stacks. * Since the ARM stacks use STMFD etc. we must set r13 to the top end * of the stack memory. */ #ifdef VERBOSE_INIT_ARM printf("init subsystems: stacks "); #endif set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); /* * Well we should set a data abort handler. * Once things get going this will change as we will need a proper * handler. * Until then we will use a handler that just panics but tells us * why. * Initialisation of the vectors will just panic on a data abort. * This just fills in a slightly better one. */ #ifdef VERBOSE_INIT_ARM printf("vectors "); #endif data_abort_handler_address = (u_int)data_abort_handler; prefetch_abort_handler_address = (u_int)prefetch_abort_handler; undefined_handler_address = (u_int)undefinedinstruction_bounce; /* Initialise the undefined instruction handlers */ #ifdef VERBOSE_INIT_ARM printf("undefined "); #endif undefined_init(); /* Load memory into UVM. */ #ifdef VERBOSE_INIT_ARM printf("page "); #endif uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ uvm_page_physload(atop(physical_freestart), atop(physical_freeend), atop(physical_freestart), atop(physical_freeend), 0); /* Boot strap pmap telling it where the kernel page table is */ #ifdef VERBOSE_INIT_ARM printf("pmap "); #endif pmap_bootstrap((pd_entry_t *)kernel_l1pt.pv_va, KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); /* Update dump information */ cpu_kcore_hdr.pmap_kernel_l1 = (u_int32_t)pmap_kernel()->pm_l1; cpu_kcore_hdr.pmap_kernel_l2 = (u_int32_t)&(pmap_kernel()->pm_l2); /* Setup the IRQ system */ #ifdef VERBOSE_INIT_ARM printf("irq "); #endif i80321intc_intr_init(); #ifdef VERBOSE_INIT_ARM printf("done.\n"); #endif #ifdef DDB db_machine_init(); /* Firmware doesn't load symbols. */ ddb_init(); if (boothowto & RB_KDB) Debugger(); #endif /* We return the new stack pointer address */ return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); }
/* * u_int initarm(...) * * Initial entry point on startup. This gets called before main() is * entered. * It should be responsible for setting up everything that must be * in place when main is called. * This includes * Taking a copy of the boot configuration structure. * Initialising the physical console so characters can be printed. * Setting up page tables for the kernel * Relocating the kernel to the bottom of physical memory */ u_int initarm(void *arg) { extern char _end[]; extern vaddr_t startup_pagetable; extern struct btinfo_common bootinfo; struct btinfo_common *btinfo = &bootinfo; struct btinfo_model *model = NULL; struct btinfo_memory *memory = NULL; struct btinfo_video *video = NULL; struct btinfo_bootargs *args = NULL; u_int l1pagetable, _end_physical; int loop, loop1, n, i; /* * Heads up ... Setup the CPU / MMU / TLB functions */ if (set_cpufuncs()) panic("cpu not recognized!"); /* map some peripheral registers at static I/O area. */ pmap_devmap_bootstrap(startup_pagetable, epoc32_devmap); bootconfig.dramblocks = 0; while (btinfo->type != BTINFO_NONE) { switch (btinfo->type) { case BTINFO_MODEL: model = (struct btinfo_model *)btinfo; btinfo = &(model + 1)->common; strncpy(epoc32_model, model->model, sizeof(epoc32_model)); break; case BTINFO_MEMORY: memory = (struct btinfo_memory *)btinfo; btinfo = &(memory + 1)->common; /* * Fake bootconfig structure for the benefit of pmap.c */ i = bootconfig.dramblocks; bootconfig.dram[i].address = memory->address; bootconfig.dram[i].pages = memory->size / PAGE_SIZE; bootconfig.dramblocks++; break; case BTINFO_VIDEO: video = (struct btinfo_video *)btinfo; btinfo = &(video + 1)->common; epoc32_fb_width = video->width; epoc32_fb_height = video->height; break; case BTINFO_BOOTARGS: args = (struct btinfo_bootargs *)btinfo; btinfo = &(args + 1)->common; memcpy(bootargs, args->bootargs, min(sizeof(bootargs), sizeof(args->bootargs))); bootargs[sizeof(bootargs) - 1] = '\0'; boot_args = bootargs; break; default: #define NEXT_BOOTINFO(bi) (struct btinfo_common *)((char *)bi + (bi)->len) btinfo = NEXT_BOOTINFO(btinfo); } } if (bootconfig.dramblocks == 0) panic("BTINFO_MEMORY not found"); consinit(); if (boot_args != NULL) parse_mi_bootargs(boot_args); physical_start = bootconfig.dram[0].address; physical_freestart = bootconfig.dram[0].address; physical_freeend = KERNEL_TEXT_BASE; free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; #define alloc_pages(var, np) \ physical_freeend -= ((np) * PAGE_SIZE); \ if (physical_freeend < physical_freestart) \ panic("initarm: out of memory"); \ (var) = physical_freeend; \ free_pages -= (np); \ memset((char *)(var), 0, ((np) * PAGE_SIZE)); loop1 = 0; for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { /* Are we 16KB aligned for an L1 ? */ if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0 && kernel_l1pt.pv_pa == 0) { valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); } else { valloc_pages(kernel_pt_table[loop1], L2_TABLE_SIZE / PAGE_SIZE); ++loop1; } } /* This should never be able to happen but better confirm that. */ if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE - 1)) != 0) panic("initarm: Failed to align the kernel page directory"); /* * Allocate a page for the system page mapped to V0x00000000 * This page will just contain the system vectors and can be * shared by all processes. */ alloc_pages(systempage.pv_pa, 1); /* Allocate stacks for all modes */ valloc_pages(irqstack, IRQ_STACK_SIZE); valloc_pages(abtstack, ABT_STACK_SIZE); valloc_pages(undstack, UND_STACK_SIZE); valloc_pages(kernelstack, UPAGES); alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); /* * Now we start construction of the L1 page table * We start by mapping the L2 page tables into the L1. * This means that we can replace L1 mappings later on if necessary */ l1pagetable = kernel_l1pt.pv_va; /* Map the L2 pages tables in the L1 page table */ pmap_link_l2pt(l1pagetable, 0x00000000, &kernel_pt_table[KERNEL_PT_SYS]); pmap_link_l2pt(l1pagetable, KERNEL_BASE, &kernel_pt_table[KERNEL_PT_KERNEL]); /* update the top of the kernel VM */ pmap_curmaxkvaddr = KERNEL_VM_BASE; /* Now we fill in the L2 pagetable for the kernel static code/data */ { extern char etext[]; size_t textsize = (uintptr_t) etext - KERNEL_TEXT_BASE; size_t totalsize = (uintptr_t) _end - KERNEL_TEXT_BASE; size_t datasize; PhysMem *dram = bootconfig.dram; u_int logical, physical, size; textsize = (textsize + PGOFSET) & ~PGOFSET; totalsize = (totalsize + PGOFSET) & ~PGOFSET; datasize = totalsize - textsize; /* data and bss */ logical = KERNEL_OFFSET; /* offset of kernel in RAM */ physical = KERNEL_OFFSET; i = 0; size = dram[i].pages * PAGE_SIZE - physical; /* Map kernel text section. */ while (1 /*CONSTINT*/) { size = pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, dram[i].address + physical, textsize < size ? textsize : size, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); logical += size; physical += size; textsize -= size; if (physical >= dram[i].pages * PAGE_SIZE) { i++; size = dram[i].pages * PAGE_SIZE; physical = 0; } if (textsize == 0) break; } size = dram[i].pages * PAGE_SIZE - physical; /* Map data and bss section. */ while (1 /*CONSTINT*/) { size = pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, dram[i].address + physical, datasize < size ? datasize : size, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); logical += size; physical += size; datasize -= size; if (physical >= dram[i].pages * PAGE_SIZE) { i++; size = dram[i].pages * PAGE_SIZE; physical = 0; } if (datasize == 0) break; } _end_physical = dram[i].address + physical; n = i; physical_end = dram[n].address + dram[n].pages * PAGE_SIZE; n++; } /* Map the stack pages */ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE); for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); /* Map the vector page. */ pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_devmap_bootstrap(l1pagetable, epoc32_devmap); pmap_devmap_bootstrap(l1pagetable, epoc32_fb_devmap); epoc32_fb_addr = ARM7XX_FB_VBASE; /* * Now we have the real page tables in place so we can switch to them. * Once this is done we will be running with the REAL kernel page * tables. */ /* Switch tables */ cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); cpu_setttb(kernel_l1pt.pv_pa, true); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); /* * Moved from cpu_startup() as data_abort_handler() references * this during uvm init */ uvm_lwp_setuarea(&lwp0, kernelstack.pv_va); arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL); /* * Pages were allocated during the secondary bootstrap for the * stacks for different CPU modes. * We must now set the r13 registers in the different CPU modes to * point to these stacks. * Since the ARM stacks use STMFD etc. we must set r13 to the top end * of the stack memory. */ set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); /* * Well we should set a data abort handler. * Once things get going this will change as we will need a proper * handler. Until then we will use a handler that just panics but * tells us why. * Initialisation of the vectors will just panic on a data abort. * This just fills in a slightly better one. */ data_abort_handler_address = (u_int)data_abort_handler; prefetch_abort_handler_address = (u_int)prefetch_abort_handler; undefined_handler_address = (u_int)undefinedinstruction_bounce; /* Initialise the undefined instruction handlers */ undefined_init(); /* Load memory into UVM. */ uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ uvm_page_physload( atop(_end_physical), atop(physical_end), atop(_end_physical), atop(physical_end), VM_FREELIST_DEFAULT); physmem = bootconfig.dram[0].pages; for (i = 1; i < n; i++) physmem += bootconfig.dram[i].pages; if (physmem < 0x400000) physical_end = 0; for (loop = n; loop < bootconfig.dramblocks; loop++) { size_t start = bootconfig.dram[loop].address; size_t size = bootconfig.dram[loop].pages * PAGE_SIZE; uvm_page_physload(atop(start), atop(start + size), atop(start), atop(start + size), VM_FREELIST_DEFAULT); physmem += bootconfig.dram[loop].pages; if (physical_end == 0 && physmem >= 0x400000 / PAGE_SIZE) /* Fixup physical_end for Series5. */ physical_end = start + size; } /* Boot strap pmap telling it where the kernel page table is */ pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); #ifdef __HAVE_MEMORY_DISK__ md_root_setconf(memory_disk, sizeof memory_disk); #endif #if NKSYMS || defined(DDB) || defined(MODULAR) /* Firmware doesn't load symbols. */ ddb_init(0, NULL, NULL); #endif #ifdef DDB db_machine_init(); if (boothowto & RB_KDB) Debugger(); #endif /* We return the new stack pointer address */ return kernelstack.pv_va + USPACE_SVC_STACK_TOP; }
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++; }
void machine_startup(int argc, char *argv[], struct bootinfo *bi) { extern char edata[], end[]; vaddr_t kernend; size_t symbolsize; int i; char *p; /* * this routines stack is never polluted since stack pointer * is lower than kernel text segment, and at exiting, stack pointer * is changed to proc0. */ struct kloader_bootinfo kbi; /* Symbol table size */ symbolsize = 0; if (memcmp(&end, ELFMAG, SELFMAG) == 0) { Elf_Ehdr *eh = (void *)end; Elf_Shdr *sh = (void *)(end + eh->e_shoff); for(i = 0; i < eh->e_shnum; i++, sh++) if (sh->sh_offset > 0 && (sh->sh_offset + sh->sh_size) > symbolsize) symbolsize = sh->sh_offset + sh->sh_size; } /* Clear BSS */ memset(edata, 0, end - edata); /* Setup bootinfo */ bootinfo = &kbi.bootinfo; memcpy(bootinfo, bi, sizeof(struct bootinfo)); if (bootinfo->magic == BOOTINFO_MAGIC) { platid.dw.dw0 = bootinfo->platid_cpu; platid.dw.dw1 = bootinfo->platid_machine; } /* CPU initialize */ if (platid_match(&platid, &platid_mask_CPU_SH_3)) sh_cpu_init(CPU_ARCH_SH3, CPU_PRODUCT_7709A); else if (platid_match(&platid, &platid_mask_CPU_SH_4)) sh_cpu_init(CPU_ARCH_SH4, CPU_PRODUCT_7750); /* Start to determine heap area */ kernend = (vaddr_t)sh3_round_page(end + symbolsize); /* Setup bootstrap options */ makebootdev("wd0"); /* default boot device */ boothowto = 0; for (i = 1; i < argc; i++) { /* skip 1st arg (kernel name). */ char *cp = argv[i]; switch (*cp) { case 'b': /* boot device: -b=sd0 etc. */ p = cp + 2; #ifdef NFS if (strcmp(p, "nfs") == 0) mountroot = nfs_mountroot; else makebootdev(p); #else /* NFS */ makebootdev(p); #endif /* NFS */ break; default: BOOT_FLAG(*cp, boothowto); break; } } #ifdef MFS /* * Check to see if a mini-root was loaded into memory. It resides * at the start of the next page just after the end of BSS. */ if (boothowto & RB_MINIROOT) { size_t fssz; fssz = sh3_round_page(mfs_initminiroot((void *)kernend)); #ifdef MEMORY_DISK_DYNAMIC md_root_setconf((caddr_t)kernend, fssz); #endif kernend += fssz; } #endif /* MFS */ /* Console */ consinit(); #ifdef HPC_DEBUG_LCD dbg_lcd_test(); #endif /* copy boot parameter for kloader */ kloader_bootinfo_set(&kbi, argc, argv, bi, TRUE); /* Find memory cluster. and load to UVM */ physmem = mem_cluster_init(SH3_P1SEG_TO_PHYS(kernend)); _DPRINTF("total memory = %dMbyte\n", (int)(sh3_ptob(physmem) >> 20)); mem_cluster_load(); /* Initialize proc0 u-area */ sh_proc0_init(); /* Initialize pmap and start to address translation */ pmap_bootstrap(); /* Debugger. */ #ifdef DDB if (symbolsize) { ddb_init(symbolsize, &end, end + symbolsize); _DPRINTF("symbol size = %d byte\n", symbolsize); } if (boothowto & RB_KDB) Debugger(); #endif /* DDB */ #ifdef KGDB if (boothowto & RB_KDB) { if (kgdb_dev == NODEV) { printf("no kgdb console.\n"); } else { kgdb_debug_init = 1; kgdb_connect(1); } } #endif /* KGDB */ /* Jump to main */ __asm__ __volatile__( "jmp @%0;" "mov %1, sp" :: "r"(main),"r"(proc0.p_md.md_pcb->pcb_sf.sf_r7_bank)); /* NOTREACHED */ while (1) ; }