/* * Wait for about n microseconds (at least!). */ void DELAY(int n) { uint32_t cur, last, delta, usecs; /* * This works by polling the timer and counting the number of * microseconds that go by. */ last = mips_rd_count(); delta = usecs = 0; while (n > usecs) { cur = mips_rd_count(); /* Check to see if the timer has wrapped around. */ if (cur < last) delta += cur + (0xffffffff - last) + 1; else delta += cur - last; last = cur; if (delta >= cycles_per_usec) { usecs += delta / cycles_per_usec; delta %= cycles_per_usec; } } }
static uint64_t malta_cpu_freq(void) { uint64_t platform_counter_freq = 0; #if defined(TICK_USE_YAMON_FREQ) /* * If we are running on a board which uses YAMON firmware, * then query CPU pipeline clock from the syscon object. * If unsuccessful, use hard-coded default. */ platform_counter_freq = yamon_getcpufreq(); #elif defined(TICK_USE_MALTA_RTC) /* * If we are running on a board with the MC146818 RTC, * use it to determine CPU pipeline clock frequency. */ u_int64_t counterval[2]; /* Set RTC to binary mode. */ writertc(RTC_STATUSB, (rtcin(RTC_STATUSB) | RTCSB_BCD)); /* Busy-wait for falling edge of RTC update. */ while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0)) ; while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0)) ; counterval[0] = mips_rd_count(); /* Busy-wait for falling edge of RTC update. */ while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0)) ; while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0)) ; counterval[1] = mips_rd_count(); platform_counter_freq = counterval[1] - counterval[0]; #endif if (platform_counter_freq == 0) platform_counter_freq = MIPS_DEFAULT_HZ; return (platform_counter_freq); }
int sysarch(struct thread *td, struct sysarch_args *uap) { int error; void *tlsbase; switch (uap->op) { case MIPS_SET_TLS: td->td_md.md_tls = uap->parms; /* * If there is an user local register implementation (ULRI) * update it as well. Add the TLS and TCB offsets so the * value in this register is adjusted like in the case of the * rdhwr trap() instruction handler. * * XXXSS For more information why this offset is required see: * 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317' */ if (cpuinfo.userlocal_reg == true) { #if defined(__mips_n64) && defined(COMPAT_FREEBSD32) mips_wr_userlocal((unsigned long)(uap->parms + TLS_TP_OFFSET + TLS_TCB_SIZE32)); #else mips_wr_userlocal((unsigned long)(uap->parms + TLS_TP_OFFSET + TLS_TCB_SIZE)); #endif } return (0); case MIPS_GET_TLS: tlsbase = td->td_md.md_tls; error = copyout(&tlsbase, uap->parms, sizeof(tlsbase)); return (error); case MIPS_GET_COUNT: td->td_retval[0] = mips_rd_count(); return (0); default: break; } return (EINVAL); }
static uint64_t tick_ticker(void) { uint64_t ret; uint32_t ticktock; uint32_t t_lower_last, t_upper; /* * Disable preemption because we are working with cpu specific data. */ critical_enter(); /* * Note that even though preemption is disabled, interrupts are * still enabled. In particular there is a race with clock_intr() * reading the values of 'counter_upper' and 'counter_lower_last'. * * XXX this depends on clock_intr() being executed periodically * so that 'counter_upper' and 'counter_lower_last' are not stale. */ do { t_upper = DPCPU_GET(counter_upper); t_lower_last = DPCPU_GET(counter_lower_last); } while (t_upper != DPCPU_GET(counter_upper)); ticktock = mips_rd_count(); critical_exit(); /* COUNT register wrapped around */ if (ticktock < t_lower_last) t_upper++; ret = ((uint64_t)t_upper << 32) | ticktock; return (ret); }
static unsigned counter_get_timecount(struct timecounter *tc) { return (mips_rd_count()); }
void platform_start(__register_t a0, __register_t a1, __register_t a2, __register_t a3) { vm_offset_t kernend; uint64_t platform_counter_freq; int argc = a0; char **argv = (char **)a1; char **envp = (char **)a2; unsigned int memsize = a3; int i; /* clear the BSS and SBSS segments */ kernend = round_page((vm_offset_t)&end); memset(&edata, 0, kernend - (vm_offset_t)(&edata)); cninit(); printf("entry: platform_start()\n"); bootverbose = 1; if (bootverbose) { printf("cmd line: "); for (i = 0; i < argc; i++) printf("%s ", argv[i]); printf("\n"); printf("envp:\n"); for (i = 0; envp[i]; i += 2) printf("\t%s = %s\n", envp[i], envp[i+1]); printf("memsize = %08x\n", memsize); } realmem = btoc(memsize); mips_init(); do { #if defined(TICK_USE_YAMON_FREQ) /* * If we are running on a board which uses YAMON firmware, * then query CPU pipeline clock from the syscon object. * If unsuccessful, use hard-coded default. */ platform_counter_freq = yamon_getcpufreq(); if (platform_counter_freq == 0) platform_counter_freq = MIPS_DEFAULT_HZ; #elif defined(TICK_USE_MALTA_RTC) /* * If we are running on a board with the MC146818 RTC, * use it to determine CPU pipeline clock frequency. */ u_int64_t counterval[2]; /* Set RTC to binary mode. */ writertc(RTC_STATUSB, (rtcin(RTC_STATUSB) | RTCSB_BCD)); /* Busy-wait for falling edge of RTC update. */ while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0)) ; while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0)) ; counterval[0] = mips_rd_count(); /* Busy-wait for falling edge of RTC update. */ while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0)) ; while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0)) ; counterval[1] = mips_rd_count(); platform_counter_freq = counterval[1] - counterval[0]; #endif } while(0); mips_timer_init_params(platform_counter_freq, 0); }