Beispiel #1
0
/*
 * 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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}