/* * the new kernel is already loaded at address `code' * of size `size' and entry point `entry'. */ void reboot(void *entry, void *code, ulong size) { void (*f)(ulong, ulong, ulong); iprint("starting reboot..."); writeconf(); shutdown(0); /* * should be the only processor running now */ print("shutting down...\n"); delay(200); /* turn off buffered serial console */ serialoq = nil; /* shutdown devices */ chandevshutdown(); /* call off the dog */ clockshutdown(); splhi(); /* setup reboot trampoline function */ f = (void*)REBOOTADDR; memmove(f, rebootcode, sizeof(rebootcode)); cacheuwbinv(); l2cacheuwb(); print("rebooting..."); iprint("entry %#lux code %#lux size %ld\n", PADDR(entry), PADDR(code), size); delay(100); /* wait for uart to quiesce */ /* off we go - never to return */ cacheuwbinv(); l2cacheuwb(); (*f)(PADDR(entry), PADDR(code), size); iprint("loaded kernel returned!\n"); delay(1000); archreboot(); }
void mmurelease(Proc* proc) { Page *page, *next; /* write back dirty and invalidate l1 caches */ cacheuwbinv(); mmul2empty(proc, 0); for(page = proc->mmul2cache; page != nil; page = next){ next = page->next; if(--page->ref) panic("mmurelease: page->ref %lud", page->ref); pagechainhead(page); } if(proc->mmul2cache != nil) pagechaindone(); proc->mmul2cache = nil; mmul1empty(); /* make sure map is in memory */ /* could be smarter about how much? */ cachedwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); /* lose any possible stale tlb entries */ mmuinvalidate(); }
void mmuinit(void) { uintptr pa; PTE *l1, *l2; pa = ttbget(); l1 = KADDR(pa); /* redundant with l.s; only covers first MB of 17MB */ l1[L1X(VIRTIO)] = PHYSIO|Dom0|L1AP(Krw)|Section; idmap(l1, PHYSETHER); /* igep 9221 ethernet regs */ idmap(l1, PHYSL4PROT); idmap(l1, PHYSL3); idmap(l1, PHYSSMS); idmap(l1, PHYSDRC); idmap(l1, PHYSGPMC); /* map high vectors to start of dram, but only 4K, not 1MB */ pa -= MACHSIZE+2*1024; l2 = KADDR(pa); memset(l2, 0, 1024); /* vectors step on u-boot, but so do page tables */ l2[L2X(HVECTORS)] = PHYSDRAM|L2AP(Krw)|Small; l1[L1X(HVECTORS)] = pa|Dom0|Coarse; /* vectors -> ttb-machsize-2k */ coherence(); cacheuwbinv(); l2cacheuwbinv(); mmuinvalidate(); m->mmul1 = l1; // mmudump(l1); /* DEBUG */ }
/* map `mbs' megabytes from virt to phys */ void mmumap(uintptr virt, uintptr phys, int mbs) { uint off; PTE *l1; phys &= ~(MB-1); virt &= ~(MB-1); l1 = KADDR(ttbget()); for (off = 0; mbs-- > 0; off += MB) l1[L1X(virt + off)] = (phys + off) | Dom0 | L1AP(Krw) | Section; cacheuwbinv(); l2cacheuwbinv(); mmuinvalidate(); }
void mmuswitch(Proc* proc) { int x; PTE *l1; Page *page; /* do kprocs get here and if so, do they need to? */ if(m->mmupid == proc->pid && !proc->newtlb) return; m->mmupid = proc->pid; /* write back dirty and invalidate l1 caches */ cacheuwbinv(); if(proc->newtlb){ mmul2empty(proc, 1); proc->newtlb = 0; } mmul1empty(); /* move in new map */ l1 = m->mmul1; for(page = proc->mmul2; page != nil; page = page->next){ x = page->daddr; l1[x] = PPN(page->pa)|Dom0|Coarse; /* know here that L1lo < x < L1hi */ if(x+1 - m->mmul1lo < m->mmul1hi - x) m->mmul1lo = x+1; else m->mmul1hi = x; } /* make sure map is in memory */ /* could be smarter about how much? */ cachedwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE)); /* lose any possible stale tlb entries */ mmuinvalidate(); //print("mmuswitch l1lo %d l1hi %d %d\n", // m->mmul1lo, m->mmul1hi, proc->kp); }
void trapinit(void) { Vpage0 *vpage0; intrsoff(); /* set up the exception vectors */ vpage0 = (Vpage0*)HVECTORS; memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); cacheuwbinv(); setr13(PsrMfiq, (u32int*)(FIQSTKTOP)); setr13(PsrMirq, m->irqstack+nelem(m->irqstack)); setr13(PsrMabt, m->abtstack+nelem(m->abtstack)); setr13(PsrMund, m->undstack+nelem(m->undstack)); setr13(PsrMsys, m->undstack+nelem(m->sysstack)); coherence(); }
void main(void) { // int i; extern char bdata[], edata[], end[], etext[]; static ulong vfy = 0xcafebabe; /* l.s has already printed "Plan 9 from Be" */ // m = mach; /* now done in l.s */ /* realign data seg; apparently -H0 -R4096 does not pad the text seg */ if (vfy != 0xcafebabe) { // wave('<'); wave('-'); memmove(bdata, etext, edata - bdata); } /* * once data segment is in place, always zero bss since we may * have been loaded by another Plan 9 kernel. */ memset(edata, 0, end - edata); /* zero BSS */ cacheuwbinv(); l2cacheuwbinv(); if (vfy != 0xcafebabe) panic("data segment misaligned"); vfy = 0; wave('l'); machinit(); mmuinit(); optionsinit("/boot/boot boot"); quotefmtinstall(); /* want plan9.ini to be able to affect memory sizing in confinit */ plan9iniinit(); /* before we step on plan9.ini in low memory */ trapinit(); /* so confinit can probe memory to size it */ confinit(); /* figures out amount of memory */ /* xinit prints (if it can), so finish up the banner here. */ delay(500); iprint("l Labs\n\n"); delay(500); xinit(); mainmem->flags |= POOL_ANTAGONISM /* | POOL_PARANOIA */ ; /* * Printinit will cause the first malloc call. * (printinit->qopen->malloc) unless any of the * above (like clockinit) do an irqenable, which * will call malloc. * If the system dies here it's probably due * to malloc(->xalloc) not being initialised * correctly, or the data segment is misaligned * (it's amazing how far you can get with * things like that completely broken). * * (Should be) boilerplate from here on. */ archreset(); /* configure clock signals */ clockinit(); /* start clocks */ timersinit(); watchdoginit(); delay(250); /* let uart catch up */ printinit(); // kbdenable(); cpuidprint(); // chkmissing(); procinit0(); initseg(); dmainit(); links(); conf.monitor = 1; screeninit(); chandevreset(); /* most devices are discovered here */ // i8250console(); /* too early; see init0 */ pageinit(); swapinit(); userinit(); schedinit(); }