2004-09-23 22:45:36 +00:00
|
|
|
/* $NetBSD: i80321_timer.c,v 1.7 2003/07/27 04:52:28 thorpej Exp $ */
|
|
|
|
|
2005-01-05 21:58:49 +00:00
|
|
|
/*-
|
2004-09-23 22:45:36 +00:00
|
|
|
* Copyright (c) 2001, 2002 Wasabi Systems, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
|
|
|
|
*
|
|
|
|
* 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 for the NetBSD Project by
|
|
|
|
* Wasabi Systems, Inc.
|
|
|
|
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
|
|
|
* or promote products derived from this software without specific prior
|
|
|
|
* written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Timer/clock support for the Intel i80321 I/O processor.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/module.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <sys/rman.h>
|
|
|
|
#include <sys/timetc.h>
|
|
|
|
|
|
|
|
#include <machine/bus.h>
|
Tweak how the MD code calls the fooclock() methods some. Instead of
passing a pointer to an opaque clockframe structure and requiring the
MD code to supply CLKF_FOO() macros to extract needed values out of the
opaque structure, just pass the needed values directly. In practice this
means passing the pair (usermode, pc) to hardclock() and profclock() and
passing the boolean (usermode) to hardclock_cpu() and hardclock_process().
Other details:
- Axe clockframe and CLKF_FOO() macros on all architectures. Basically,
all the archs were taking a trapframe and converting it into a clockframe
one way or another. Now they can just extract the PC and usermode values
directly out of the trapframe and pass it to fooclock().
- Renamed hardclock_process() to hardclock_cpu() as the latter is more
accurate.
- On Alpha, we now run profclock() at hz (profhz == hz) rather than at
the slower stathz.
- On Alpha, for the TurboLaser machines that don't have an 8254
timecounter, call hardclock() directly. This removes an extra
conditional check from every clock interrupt on Alpha on the BSP.
There is probably room for even further pruning here by changing Alpha
to use the simplified timecounter we use on x86 with the lapic timer
since we don't get interrupts from the 8254 on Alpha anyway.
- On x86, clkintr() shouldn't ever be called now unless using_lapic_timer
is false, so add a KASSERT() to that affect and remove a condition
to slightly optimize the non-lapic case.
- Change prototypeof arm_handler_execute() so that it's first arg is a
trapframe pointer rather than a void pointer for clarity.
- Use KCOUNT macro in profclock() to lookup the kernel profiling bucket.
Tested on: alpha, amd64, arm, i386, ia64, sparc64
Reviewed by: bde (mostly)
2005-12-22 22:16:09 +00:00
|
|
|
#include <machine/cpu.h>
|
2004-09-23 22:45:36 +00:00
|
|
|
#include <machine/cpufunc.h>
|
Tweak how the MD code calls the fooclock() methods some. Instead of
passing a pointer to an opaque clockframe structure and requiring the
MD code to supply CLKF_FOO() macros to extract needed values out of the
opaque structure, just pass the needed values directly. In practice this
means passing the pair (usermode, pc) to hardclock() and profclock() and
passing the boolean (usermode) to hardclock_cpu() and hardclock_process().
Other details:
- Axe clockframe and CLKF_FOO() macros on all architectures. Basically,
all the archs were taking a trapframe and converting it into a clockframe
one way or another. Now they can just extract the PC and usermode values
directly out of the trapframe and pass it to fooclock().
- Renamed hardclock_process() to hardclock_cpu() as the latter is more
accurate.
- On Alpha, we now run profclock() at hz (profhz == hz) rather than at
the slower stathz.
- On Alpha, for the TurboLaser machines that don't have an 8254
timecounter, call hardclock() directly. This removes an extra
conditional check from every clock interrupt on Alpha on the BSP.
There is probably room for even further pruning here by changing Alpha
to use the simplified timecounter we use on x86 with the lapic timer
since we don't get interrupts from the 8254 on Alpha anyway.
- On x86, clkintr() shouldn't ever be called now unless using_lapic_timer
is false, so add a KASSERT() to that affect and remove a condition
to slightly optimize the non-lapic case.
- Change prototypeof arm_handler_execute() so that it's first arg is a
trapframe pointer rather than a void pointer for clarity.
- Use KCOUNT macro in profclock() to lookup the kernel profiling bucket.
Tested on: alpha, amd64, arm, i386, ia64, sparc64
Reviewed by: bde (mostly)
2005-12-22 22:16:09 +00:00
|
|
|
#include <machine/frame.h>
|
2004-09-23 22:45:36 +00:00
|
|
|
#include <machine/resource.h>
|
|
|
|
#include <machine/intr.h>
|
|
|
|
#include <arm/xscale/i80321/i80321reg.h>
|
|
|
|
#include <arm/xscale/i80321/i80321var.h>
|
|
|
|
|
|
|
|
#include <arm/xscale/xscalevar.h>
|
|
|
|
|
2005-12-09 23:52:51 +00:00
|
|
|
#include "opt_timer.h"
|
|
|
|
|
2005-01-15 18:55:22 +00:00
|
|
|
void (*i80321_hardclock_hook)(void) = NULL;
|
2004-09-23 22:45:36 +00:00
|
|
|
struct i80321_timer_softc {
|
|
|
|
device_t dev;
|
|
|
|
} timer_softc;
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned i80321_timer_get_timecount(struct timecounter *tc);
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t counts_per_hz;
|
|
|
|
|
|
|
|
static int ticked = 0;
|
|
|
|
|
2005-12-09 23:52:51 +00:00
|
|
|
#ifndef COUNTS_PER_SEC
|
2004-09-23 22:45:36 +00:00
|
|
|
#define COUNTS_PER_SEC 200000000 /* 200MHz */
|
2005-12-09 23:52:51 +00:00
|
|
|
#endif
|
|
|
|
|
2004-09-23 22:45:36 +00:00
|
|
|
#define COUNTS_PER_USEC (COUNTS_PER_SEC / 1000000)
|
|
|
|
|
|
|
|
static struct timecounter i80321_timer_timecounter = {
|
|
|
|
i80321_timer_get_timecount, /* get_timecount */
|
|
|
|
NULL, /* no poll_pps */
|
|
|
|
~0u, /* counter_mask */
|
2005-10-17 14:51:01 +00:00
|
|
|
COUNTS_PER_SEC * 3, /* frequency */
|
2004-09-23 22:45:36 +00:00
|
|
|
"i80321 timer", /* name */
|
|
|
|
1000 /* quality */
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
i80321_timer_probe(device_t dev)
|
|
|
|
{
|
2005-01-15 16:57:00 +00:00
|
|
|
|
|
|
|
device_set_desc(dev, "i80321 timer");
|
2004-09-23 22:45:36 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
i80321_timer_attach(device_t dev)
|
|
|
|
{
|
|
|
|
timer_softc.dev = dev;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static device_method_t i80321_timer_methods[] = {
|
|
|
|
DEVMETHOD(device_probe, i80321_timer_probe),
|
|
|
|
DEVMETHOD(device_attach, i80321_timer_attach),
|
|
|
|
{0, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t i80321_timer_driver = {
|
|
|
|
"itimer",
|
|
|
|
i80321_timer_methods,
|
|
|
|
sizeof(struct i80321_timer_softc),
|
|
|
|
};
|
|
|
|
static devclass_t i80321_timer_devclass;
|
|
|
|
|
|
|
|
DRIVER_MODULE(itimer, iq, i80321_timer_driver, i80321_timer_devclass, 0, 0);
|
|
|
|
|
|
|
|
void counterhandler(void *);
|
|
|
|
void clockhandler(void *);
|
|
|
|
|
|
|
|
|
|
|
|
static __inline uint32_t
|
|
|
|
tmr1_read(void)
|
|
|
|
{
|
|
|
|
uint32_t rv;
|
|
|
|
|
|
|
|
__asm __volatile("mrc p6, 0, %0, c1, c1, 0"
|
|
|
|
: "=r" (rv));
|
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
tmr1_write(uint32_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
__asm __volatile("mcr p6, 0, %0, c1, c1, 0"
|
|
|
|
:
|
|
|
|
: "r" (val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline uint32_t
|
|
|
|
tcr1_read(void)
|
|
|
|
{
|
|
|
|
uint32_t rv;
|
|
|
|
|
|
|
|
__asm __volatile("mrc p6, 0, %0, c3, c1, 0"
|
|
|
|
: "=r" (rv));
|
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
static __inline void
|
|
|
|
tcr1_write(uint32_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
__asm __volatile("mcr p6, 0, %0, c3, c1, 0"
|
|
|
|
:
|
|
|
|
: "r" (val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
trr1_write(uint32_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
__asm __volatile("mcr p6, 1, %0, c5, c1, 0"
|
|
|
|
:
|
|
|
|
: "r" (val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline uint32_t
|
|
|
|
tmr0_read(void)
|
|
|
|
{
|
|
|
|
uint32_t rv;
|
|
|
|
|
|
|
|
__asm __volatile("mrc p6, 0, %0, c0, c1, 0"
|
|
|
|
: "=r" (rv));
|
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
tmr0_write(uint32_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
__asm __volatile("mcr p6, 0, %0, c0, c1, 0"
|
|
|
|
:
|
|
|
|
: "r" (val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline uint32_t
|
|
|
|
tcr0_read(void)
|
|
|
|
{
|
|
|
|
uint32_t rv;
|
|
|
|
|
|
|
|
__asm __volatile("mrc p6, 0, %0, c2, c1, 0"
|
|
|
|
: "=r" (rv));
|
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
static __inline void
|
|
|
|
tcr0_write(uint32_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
__asm __volatile("mcr p6, 0, %0, c2, c1, 0"
|
|
|
|
:
|
|
|
|
: "r" (val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
trr0_write(uint32_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
__asm __volatile("mcr p6, 0, %0, c4, c1, 0"
|
|
|
|
:
|
|
|
|
: "r" (val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
tisr_write(uint32_t val)
|
|
|
|
{
|
|
|
|
|
|
|
|
__asm __volatile("mcr p6, 0, %0, c6, c1, 0"
|
|
|
|
:
|
|
|
|
: "r" (val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline uint32_t
|
|
|
|
tisr_read(void)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
__asm __volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (ret));
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
i80321_timer_get_timecount(struct timecounter *tc)
|
|
|
|
{
|
2005-10-17 14:51:01 +00:00
|
|
|
uint32_t ret;
|
|
|
|
|
|
|
|
__asm __volatile("mrc p14, 0, %0, c1, c0, 0\n"
|
|
|
|
: "=r" (ret));
|
|
|
|
return (ret);
|
2004-09-23 22:45:36 +00:00
|
|
|
}
|
2005-10-03 14:19:55 +00:00
|
|
|
|
2004-09-23 22:45:36 +00:00
|
|
|
/*
|
|
|
|
* i80321_calibrate_delay:
|
|
|
|
*
|
|
|
|
* Calibrate the delay loop.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
i80321_calibrate_delay(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Just use hz=100 for now -- we'll adjust it, if necessary,
|
|
|
|
* in cpu_initclocks().
|
|
|
|
*/
|
|
|
|
counts_per_hz = COUNTS_PER_SEC / 100;
|
|
|
|
|
|
|
|
tmr0_write(0); /* stop timer */
|
|
|
|
tisr_write(TISR_TMR0); /* clear interrupt */
|
|
|
|
trr0_write(counts_per_hz); /* reload value */
|
|
|
|
tcr0_write(counts_per_hz); /* current value */
|
|
|
|
|
|
|
|
tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* cpu_initclocks:
|
|
|
|
*
|
|
|
|
* Initialize the clock and get them going.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
cpu_initclocks(void)
|
|
|
|
{
|
|
|
|
u_int oldirqstate;
|
|
|
|
struct resource *irq;
|
|
|
|
int rid = 0;
|
|
|
|
void *ihl;
|
|
|
|
device_t dev = timer_softc.dev;
|
|
|
|
|
|
|
|
if (hz < 50 || COUNTS_PER_SEC % hz) {
|
|
|
|
printf("Cannot get %d Hz clock; using 100 Hz\n", hz);
|
|
|
|
hz = 100;
|
|
|
|
}
|
|
|
|
tick = 1000000 / hz; /* number of microseconds between interrupts */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We only have one timer available; stathz and profhz are
|
|
|
|
* always left as 0 (the upper-layer clock code deals with
|
|
|
|
* this situation).
|
|
|
|
*/
|
|
|
|
if (stathz != 0)
|
|
|
|
printf("Cannot get %d Hz statclock\n", stathz);
|
|
|
|
stathz = 0;
|
|
|
|
|
|
|
|
if (profhz != 0)
|
|
|
|
printf("Cannot get %d Hz profclock\n", profhz);
|
|
|
|
profhz = 0;
|
|
|
|
|
|
|
|
/* Report the clock frequency. */
|
|
|
|
|
|
|
|
oldirqstate = disable_interrupts(I32_bit);
|
|
|
|
|
|
|
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, ICU_INT_TMR0,
|
|
|
|
ICU_INT_TMR0, 1, RF_ACTIVE);
|
|
|
|
if (!irq)
|
|
|
|
panic("Unable to setup the clock irq handler.\n");
|
|
|
|
else
|
|
|
|
bus_setup_intr(dev, irq, INTR_TYPE_CLK | INTR_FAST,
|
|
|
|
clockhandler, NULL, &ihl);
|
|
|
|
tmr0_write(0); /* stop timer */
|
|
|
|
tisr_write(TISR_TMR0); /* clear interrupt */
|
|
|
|
|
|
|
|
counts_per_hz = COUNTS_PER_SEC / hz;
|
|
|
|
|
|
|
|
trr0_write(counts_per_hz); /* reload value */
|
|
|
|
tcr0_write(counts_per_hz); /* current value */
|
|
|
|
tmr0_write(TMRx_ENABLE|TMRx_RELOAD|TMRx_CSEL_CORE);
|
|
|
|
|
|
|
|
tc_init(&i80321_timer_timecounter);
|
|
|
|
restore_interrupts(oldirqstate);
|
2005-10-17 14:51:01 +00:00
|
|
|
rid = 0;
|
|
|
|
/* Enable the clock count register. */
|
|
|
|
__asm __volatile("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (rid));
|
|
|
|
rid &= ~(1 << 3);
|
|
|
|
rid |= (1 << 2) | 1;
|
|
|
|
__asm __volatile("mcr p14, 0, %0, c0, c0, 0\n"
|
|
|
|
: : "r" (rid));
|
2004-09-23 22:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DELAY:
|
|
|
|
*
|
|
|
|
* Delay for at least N microseconds.
|
|
|
|
*/
|
|
|
|
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 = tcr0_read();
|
|
|
|
delta = usecs = 0;
|
|
|
|
|
|
|
|
while (n > usecs) {
|
|
|
|
cur = tcr0_read();
|
|
|
|
|
|
|
|
/* Check to see if the timer has wrapped around. */
|
|
|
|
if (last < cur)
|
|
|
|
delta += (last + (counts_per_hz - cur));
|
|
|
|
else
|
|
|
|
delta += (last - cur);
|
|
|
|
|
|
|
|
last = cur;
|
|
|
|
|
|
|
|
if (delta >= COUNTS_PER_USEC) {
|
|
|
|
usecs += delta / COUNTS_PER_USEC;
|
|
|
|
delta %= COUNTS_PER_USEC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* clockhandler:
|
|
|
|
*
|
|
|
|
* Handle the hardclock interrupt.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
clockhandler(void *arg)
|
|
|
|
{
|
Tweak how the MD code calls the fooclock() methods some. Instead of
passing a pointer to an opaque clockframe structure and requiring the
MD code to supply CLKF_FOO() macros to extract needed values out of the
opaque structure, just pass the needed values directly. In practice this
means passing the pair (usermode, pc) to hardclock() and profclock() and
passing the boolean (usermode) to hardclock_cpu() and hardclock_process().
Other details:
- Axe clockframe and CLKF_FOO() macros on all architectures. Basically,
all the archs were taking a trapframe and converting it into a clockframe
one way or another. Now they can just extract the PC and usermode values
directly out of the trapframe and pass it to fooclock().
- Renamed hardclock_process() to hardclock_cpu() as the latter is more
accurate.
- On Alpha, we now run profclock() at hz (profhz == hz) rather than at
the slower stathz.
- On Alpha, for the TurboLaser machines that don't have an 8254
timecounter, call hardclock() directly. This removes an extra
conditional check from every clock interrupt on Alpha on the BSP.
There is probably room for even further pruning here by changing Alpha
to use the simplified timecounter we use on x86 with the lapic timer
since we don't get interrupts from the 8254 on Alpha anyway.
- On x86, clkintr() shouldn't ever be called now unless using_lapic_timer
is false, so add a KASSERT() to that affect and remove a condition
to slightly optimize the non-lapic case.
- Change prototypeof arm_handler_execute() so that it's first arg is a
trapframe pointer rather than a void pointer for clarity.
- Use KCOUNT macro in profclock() to lookup the kernel profiling bucket.
Tested on: alpha, amd64, arm, i386, ia64, sparc64
Reviewed by: bde (mostly)
2005-12-22 22:16:09 +00:00
|
|
|
struct trapframe *frame = arg;
|
2004-09-23 22:45:36 +00:00
|
|
|
|
|
|
|
ticked++;
|
|
|
|
tisr_write(TISR_TMR0);
|
Tweak how the MD code calls the fooclock() methods some. Instead of
passing a pointer to an opaque clockframe structure and requiring the
MD code to supply CLKF_FOO() macros to extract needed values out of the
opaque structure, just pass the needed values directly. In practice this
means passing the pair (usermode, pc) to hardclock() and profclock() and
passing the boolean (usermode) to hardclock_cpu() and hardclock_process().
Other details:
- Axe clockframe and CLKF_FOO() macros on all architectures. Basically,
all the archs were taking a trapframe and converting it into a clockframe
one way or another. Now they can just extract the PC and usermode values
directly out of the trapframe and pass it to fooclock().
- Renamed hardclock_process() to hardclock_cpu() as the latter is more
accurate.
- On Alpha, we now run profclock() at hz (profhz == hz) rather than at
the slower stathz.
- On Alpha, for the TurboLaser machines that don't have an 8254
timecounter, call hardclock() directly. This removes an extra
conditional check from every clock interrupt on Alpha on the BSP.
There is probably room for even further pruning here by changing Alpha
to use the simplified timecounter we use on x86 with the lapic timer
since we don't get interrupts from the 8254 on Alpha anyway.
- On x86, clkintr() shouldn't ever be called now unless using_lapic_timer
is false, so add a KASSERT() to that affect and remove a condition
to slightly optimize the non-lapic case.
- Change prototypeof arm_handler_execute() so that it's first arg is a
trapframe pointer rather than a void pointer for clarity.
- Use KCOUNT macro in profclock() to lookup the kernel profiling bucket.
Tested on: alpha, amd64, arm, i386, ia64, sparc64
Reviewed by: bde (mostly)
2005-12-22 22:16:09 +00:00
|
|
|
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
|
2004-09-23 22:45:36 +00:00
|
|
|
|
2005-01-15 18:55:22 +00:00
|
|
|
if (i80321_hardclock_hook != NULL)
|
|
|
|
(*i80321_hardclock_hook)();
|
2004-09-23 22:45:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cpu_startprofclock(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cpu_stopprofclock(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|