/* * 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 clockinit(void) { int i, s; Timerregs *tn; clockshutdown(); /* turn cycle counter on */ cpwrsc(0, CpCLD, CpCLDena, CpCLDenacyc, 1<<31); /* turn all counters on and clear the cycle counter */ cpwrsc(0, CpCLD, CpCLDena, CpCLDenapmnc, 1<<2 | 1); /* let users read the cycle counter directly */ cpwrsc(0, CpCLD, CpCLDena, CpCLDenapmnc, 1); ilock(&clklck); m->fastclock = 1; m->ticks = ticks = 0; /* * T0 is a freerunning timer (cycle counter); it wraps, * automatically reloads, and does not dispatch interrupts. */ tn = (Timerregs *)Tn0; tn->tcrr = Freebase; /* count up to 0 */ tn->tldr = Freebase; coherence(); tn->tclr = Ar | St; iunlock(&clklck); /* * T1 is the interrupting timer and does not participate * in measuring time. It is initially set to HZ. */ tn = (Timerregs *)Tn1; irqenable(Tn0irq+1, clockintr, tn, "clock"); ilock(&clklck); tn->tcrr = -Tcycles; /* approx.; count up to 0 */ tn->tldr = -Tcycles; coherence(); tn->tclr = Ar | St; coherence(); tn->tier = Ovf_it; coherence(); iunlock(&clklck); /* * verify sanity of timer1 */ s = spllo(); /* risky */ for (i = 0; i < 5 && ticks == 0; i++) { delay(10); cachedwbinvse(&ticks, sizeof ticks); } splx(s); if (ticks == 0) { if (tn->tcrr == 0) panic("clock not interrupting"); else if (tn->tcrr == tn->tldr) panic("clock not ticking at all"); #ifdef PARANOID else panic("clock running very slowly"); #endif } guessmips(issue1loop, "single"); if (Debug) iprint(", "); guessmips(issue2loop, "dual"); if (Debug) iprint("\n"); /* * m->delayloop should be the number of delay loop iterations * needed to consume 1 ms. 2 is min. instructions in the delay loop. */ m->delayloop = m->cpuhz / (1000 * 2); // iprint("m->delayloop = %lud\n", m->delayloop); /* * desynchronize the processor clocks so that they all don't * try to resched at the same time. */ delay(m->machno*2); }
/* * called on a cpu other than 0 from cpureset in l.s, * from _vrst in lexception.s. * mmu and l1 (and system-wide l2) caches and coherency (smpon) are on, * but interrupts are disabled. * our mmu is using an exact copy of cpu0's l1 page table * as it was after userinit ran. */ void cpustart(void) { int ms; ulong *evp; Power *pwr; up = nil; if (active.machs & (1<<m->machno)) { serialputc('?'); serialputc('r'); panic("cpu%d: resetting after start", m->machno); } assert(m->machno != 0); errata(); cortexa9cachecfg(); memdiag(&testmem); machinit(); /* bumps nmach, adds bit to machs */ machoff(m->machno); /* not ready to go yet */ /* clock signals and scu are system-wide and already on */ clockshutdown(); /* kill any watch-dog timer */ trapinit(); clockinit(); /* sets loop delay */ timersinit(); cpuidprint(); /* * notify cpu0 that we're up so it can proceed to l1diag. */ evp = (ulong *)soc.exceptvec; /* magic */ *evp = m->machno; coherence(); l1diag(); /* contend with other cpus to verify sanity */ /* * pwr->noiopwr == 0 * pwr->detect == 0x1ff (default, all disabled) */ pwr = (Power *)soc.power; assert(pwr->gatests == MASK(7)); /* everything has power */ /* * 8169 has to initialise before we get past this, thus cpu0 * has to schedule processes first. */ if (Debug) iprint("cpu%d: waiting for 8169\n", m->machno); for (ms = 0; !l1ptstable.word && ms < 5000; ms += 10) { delay(10); cachedinvse(&l1ptstable.word, sizeof l1ptstable.word); } if (!l1ptstable.word) iprint("cpu%d: 8169 unreasonably slow; proceeding\n", m->machno); /* now safe to copy cpu0's l1 pt in mmuinit */ mmuinit(); /* update our l1 pt from cpu0's */ fpon(); machon(m->machno); /* now ready to go and be scheduled */ if (Debug) iprint("cpu%d: scheding\n", m->machno); schedinit(); panic("cpu%d: schedinit returned", m->machno); }