Fix another botch on migration to MI mips3_clock.c for algor in 2006:

- in algor_p????_cal_timer() functions, initialize ci_divisor_delay
  and ci_cycles_per_hz values in curcpu() for MI mips3_clock.c:mips3_delay()
  rather than obsolete and homegrown delay_divisor
- remove old _delay() stuff from locore_machdep.S
- make MI mips3_delay() work even before frequency values in curcpu()
  are initialized

Now NetBSD/algor P5064 kernel works on gxemul.

While here, add a hack for emulators:
- ignore a measured CPU frequency if the value looks unlikely

Pullup request for netbsd-4 will be sent later.
This commit is contained in:
tsutsui 2008-01-09 14:46:48 +00:00
parent cbfd19ee15
commit 774fc1f9f9
5 changed files with 82 additions and 116 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: algor_p4032_intr.c,v 1.14 2007/12/03 15:33:03 ad Exp $ */
/* $NetBSD: algor_p4032_intr.c,v 1.15 2008/01/09 14:46:48 tsutsui Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: algor_p4032_intr.c,v 1.14 2007/12/03 15:33:03 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: algor_p4032_intr.c,v 1.15 2008/01/09 14:46:48 tsutsui Exp $");
#include "opt_ddb.h"
@ -55,6 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: algor_p4032_intr.c,v 1.14 2007/12/03 15:33:03 ad Exp
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/cpu.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
@ -326,21 +327,24 @@ algor_p4032_cal_timer(bus_space_tag_t st, bus_space_handle_t sh)
REGVAL(P4032_IRR0) = 0;
/* Compute the number of cycles per second. */
/* Update CPU frequency values */
cps = ((ctrdiff[2] + ctrdiff[3]) / 2) * 16;
/* Compute the number of ticks for hz. */
cycles_per_hz = cps / hz;
/* Compute the delay divisor. */
delay_divisor = (cps / 1000000) / 2;
curcpu()->ci_cpu_freq = cps;
curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz;
curcpu()->ci_divisor_delay =
((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000);
/* XXX mips_cpu_flags isn't set here; assume CPU_MIPS_DOUBLE_COUNT */
curcpu()->ci_cycles_per_hz /= 2;
curcpu()->ci_divisor_delay /= 2;
MIPS_SET_CI_RECIPRICAL(curcpu());
printf("Timer calibration: %lu cycles/sec [(%lu, %lu) * 16]\n",
cps, ctrdiff[2], ctrdiff[3]);
curcpu()->ci_cpu_freq, ctrdiff[2], ctrdiff[3]);
printf("CPU clock speed = %lu.%02luMHz "
"(hz cycles = %lu, delay divisor = %u)\n",
cps / 1000000, (cps % 1000000) / 10000,
cycles_per_hz, delay_divisor);
"(hz cycles = %lu, delay divisor = %lu)\n",
curcpu()->ci_cpu_freq / 1000000,
(curcpu()->ci_cpu_freq % 1000000) / 10000,
curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay);
}
void *

View File

@ -1,4 +1,4 @@
/* $NetBSD: algor_p5064_intr.c,v 1.17 2007/12/03 15:33:03 ad Exp $ */
/* $NetBSD: algor_p5064_intr.c,v 1.18 2008/01/09 14:46:49 tsutsui Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -45,7 +45,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: algor_p5064_intr.c,v 1.17 2007/12/03 15:33:03 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: algor_p5064_intr.c,v 1.18 2008/01/09 14:46:49 tsutsui Exp $");
#include "opt_ddb.h"
@ -55,6 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: algor_p5064_intr.c,v 1.17 2007/12/03 15:33:03 ad Exp
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/cpu.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
@ -412,21 +413,31 @@ algor_p5064_cal_timer(bus_space_tag_t st, bus_space_handle_t sh)
REGVAL(P5064_LOCINT) = 0;
/* Compute the number of cycles per second. */
/* Update CPU frequency values */
cps = ((ctrdiff[2] + ctrdiff[3]) / 2) * 16;
/* Compute the number of ticks for hz. */
cycles_per_hz = cps / hz;
/* Compute the delay divisor. */
delay_divisor = (cps / 1000000) / 2;
#if 1
/* XXX for unaccurate emulators */
if (cps < 10 * 1000 * 1000) {
/* unlikely, use a reasonable value */
cps = 150 * 1000 * 1000;
}
#endif
curcpu()->ci_cpu_freq = cps;
curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz;
curcpu()->ci_divisor_delay =
((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000);
/* XXX mips_cpu_flags isn't set here; assume CPU_MIPS_DOUBLE_COUNT */
curcpu()->ci_cycles_per_hz /= 2;
curcpu()->ci_divisor_delay /= 2;
MIPS_SET_CI_RECIPRICAL(curcpu());
printf("Timer calibration: %lu cycles/sec [(%lu, %lu) * 16]\n",
cps, ctrdiff[2], ctrdiff[3]);
curcpu()->ci_cpu_freq, ctrdiff[2], ctrdiff[3]);
printf("CPU clock speed = %lu.%02luMHz "
"(hz cycles = %lu, delay divisor = %u)\n",
cps / 1000000, (cps % 1000000) / 10000,
cycles_per_hz, delay_divisor);
"(hz cycles = %lu, delay divisor = %lu)\n",
curcpu()->ci_cpu_freq / 1000000,
(curcpu()->ci_cpu_freq % 1000000) / 10000,
curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay);
}
void *

View File

@ -1,4 +1,4 @@
/* $NetBSD: algor_p6032_intr.c,v 1.11 2007/12/03 15:33:03 ad Exp $ */
/* $NetBSD: algor_p6032_intr.c,v 1.12 2008/01/09 14:46:49 tsutsui Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: algor_p6032_intr.c,v 1.11 2007/12/03 15:33:03 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: algor_p6032_intr.c,v 1.12 2008/01/09 14:46:49 tsutsui Exp $");
#include "opt_ddb.h"
@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: algor_p6032_intr.c,v 1.11 2007/12/03 15:33:03 ad Exp
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/cpu.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
@ -287,21 +288,24 @@ algor_p6032_cal_timer(bus_space_tag_t st, bus_space_handle_t sh)
ctrdiff[i] = endctr - startctr;
}
/* Compute the number of cycles per second. */
/* Update CPU frequency values */
cps = ((ctrdiff[2] + ctrdiff[3]) / 2) * 16;
/* Compute the number of ticks for hz. */
cycles_per_hz = cps / hz;
/* Compute the delay divisor. */
delay_divisor = (cps / 1000000) / 2;
curcpu()->ci_cpu_freq = cps;
curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz;
curcpu()->ci_divisor_delay =
((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000);
/* XXX mips_cpu_flags isn't set here; assume CPU_MIPS_DOUBLE_COUNT */
curcpu()->ci_cycles_per_hz /= 2;
curcpu()->ci_divisor_delay /= 2;
MIPS_SET_CI_RECIPRICAL(curcpu());
printf("Timer calibration: %lu cycles/sec [(%lu, %lu) * 16]\n",
cps, ctrdiff[2], ctrdiff[3]);
curcpu()->ci_cpu_freq, ctrdiff[2], ctrdiff[3]);
printf("CPU clock speed = %lu.%02luMHz "
"(hz cycles = %lu, delay divisor = %u)\n",
cps / 1000000, (cps % 1000000) / 10000,
cycles_per_hz, delay_divisor);
"(hz cycles = %lu, delay divisor = %lu)\n",
curcpu()->ci_cpu_freq / 1000000,
(curcpu()->ci_cpu_freq % 1000000) / 10000,
curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay);
}
void *

View File

@ -1,72 +1,3 @@
/* $NetBSD: locore_machdep.S,v 1.3 2005/12/11 12:16:08 christos Exp $ */
/* $NetBSD: locore_machdep.S,v 1.4 2008/01/09 14:46:49 tsutsui Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <mips/asm.h>
#include <mips/cpuregs.h>
.set noreorder
/*
* _delay(u_int N)
*
* Delay for at least (N/256) microseconds.
* This routine depends on the variable: delay_divisor,
* which should be set based on the CPU clock rate.
*/
LEAF_NOPROFILE(_delay)
/* a0 = (usecs << 8) */
/* v0 = delay_divisor */
la v0, _C_LABEL(delay_divisor)
lw v0, 0(v0)
b 1f /* jump into the loop! */
nop
/* Align the branch target to ~cache line. */
.align 5
1: bgtz a0, 1b
subu a0, a0, v0
j ra
nop
END(_delay)
.data
.globl _C_LABEL(delay_divisor)
.align 2
_C_LABEL(delay_divisor):
.word 0
/* This file intentionally left blank. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: mips3_clock.c,v 1.7 2008/01/08 14:46:28 joerg Exp $ */
/* $NetBSD: mips3_clock.c,v 1.8 2008/01/09 14:46:49 tsutsui Exp $ */
/*
* Copyright (c) 1992, 1993
@ -78,10 +78,11 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__KERNEL_RCSID(0, "$NetBSD: mips3_clock.c,v 1.7 2008/01/08 14:46:28 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: mips3_clock.c,v 1.8 2008/01/09 14:46:49 tsutsui Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/timetc.h>
#include <sys/cpu.h>
@ -96,25 +97,40 @@ __KERNEL_RCSID(0, "$NetBSD: mips3_clock.c,v 1.7 2008/01/08 14:46:28 joerg Exp $"
void
mips3_delay(int n)
{
u_long cycles_per_hz, divisor_delay;
uint32_t cur, last, delta, usecs;
last = mips3_cp0_count_read();
delta = usecs = 0;
if (curcpu()->ci_cpu_freq == 0) {
/*
* Frequency values in curcpu() are not initialized.
* Assume faster frequency since longer delays are harmless.
* Note CPU_MIPS_DOUBLE_COUNT is ignored here.
*/
#define FAST_FREQ (300 * 1000 * 1000) /* fast enough? */
cycles_per_hz = FAST_FREQ / hz;
divisor_delay = FAST_FREQ / (1000 * 1000);
} else {
cycles_per_hz = curcpu()->ci_cycles_per_hz;
divisor_delay = curcpu()->ci_divisor_delay;
}
while (n > usecs) {
cur = mips3_cp0_count_read();
/* Check to see if the timer has wrapped around. */
if (cur < last)
delta += ((curcpu()->ci_cycles_per_hz - last) + cur);
delta += ((cycles_per_hz - last) + cur);
else
delta += (cur - last);
last = cur;
if (delta >= curcpu()->ci_divisor_delay) {
usecs += delta / curcpu()->ci_divisor_delay;
delta %= curcpu()->ci_divisor_delay;
if (delta >= divisor_delay) {
usecs += delta / divisor_delay;
delta %= divisor_delay;
}
}
}