Marius Strobl 09c7f9e338 - USIII-based machines can consist of CPUs running at different
frequencies (and having different cache sizes) so use the STICK
  (System TICK) timer, which was introduced due to this and is
  driven by the same frequency across all CPUs, instead of the
  TICK timer, whose frequency varies with the CPU clock, to drive
  hardclock. We try to use the STICK counter with all CPUs that are
  USIII or beyond, even when not necessary due to identical CPUs,
  as we can can also avoid the workaround for the BlackBird erratum
  #1 there. Unfortunately, using the STICK counter currently causes
  a hang with USIIIi MP machines for reasons unknown, so we still
  use the TICK timer there (which is okay as they can only consist
  of identical CPUs).
- Given that we only (try to) synchronize the (S)TICK timers of APs
  with the BSP during startup, we could end up spinning forever in
  DELAY(9) if that function is migrated to another CPU while we're
  spinning due to clock drift afterwards, so pin to the CPU in order
  to avoid migration. Unfortunately, pinning doesn't work at the
  point DELAY(9) is required by the low-level console drivers, yet,
  so switch to a function pointer, which is updated accordingly, for
  implementing DELAY(9). For USIII and beyond, this would also allow
  to easily use the STICK counter instead of the TICK one here,
  there's no benefit in doing so however.
  While at it, use cpu_spinwait(9) for spinning in the delay-
  functions. This currently is a NOP though.
- Don't set the TICK timer of the BSP to 0 during at startup as
  there's no need to do so.
- Implement cpu_est_clockrate().
- Unfortunately, USIIIi-based machines don't provide a timecounter
  device besides the STICK and TICK counters (well, in theory the
  Tomatillo bridges have a performance counter that can be (ab)used
  as timecounter by configuring it to count bus cycles, though unlike
  the performance counter of Schizo bridges, the Tomatillo one is
  broken and counts Sun knows what in this mode). This means that
  we've to use a (S)TICK counter for timecounting, which has the old
  problem of not being in sync across CPUs, so provide an additional
  timecounter function which binds itself to the BSP but has an
  adequate low priority.
2008-09-03 17:39:19 +00:00

151 lines
3.5 KiB
ArmAsm

/*-
* Copyright (c) 2001 Jake Burkholder.
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/asm.h>
__FBSDID("$FreeBSD$");
#include <machine/asi.h>
#include <machine/asmacros.h>
#include <machine/pstate.h>
#include "assym.s"
.register %g2,#ignore
.globl kernbase
.set kernbase, KERNBASE
/*
* void _start(caddr_t metadata, u_long o1, u_long o2, u_long o3,
* u_long ofw_vec)
*/
ENTRY(btext)
ENTRY(_start)
/*
* Initialize misc. state to known values: interrupts disabled, normal
* globals, windows flushed (cr = 0, cs = nwindows - 1), no clean
* windows, pil 0, and floating point disabled.
*/
wrpr %g0, PSTATE_NORMAL, %pstate
flushw
wrpr %g0, 0, %cleanwin
wrpr %g0, 0, %pil
wr %g0, 0, %fprs
/*
* Get onto our per-CPU panic stack, which precedes the struct pcpu in
* the per-CPU page.
*/
SET(pcpu0 + (PCPU_PAGES * PAGE_SIZE) - PC_SIZEOF, %l1, %l0)
sub %l0, SPOFF + CCFSZ, %sp
/*
* Enable interrupts.
*/
wrpr %g0, PSTATE_KERNEL, %pstate
/*
* Do initial bootstrap to setup pmap and thread0.
*/
call sparc64_init
nop
/*
* Get onto thread0's kstack.
*/
sub PCB_REG, SPOFF + CCFSZ, %sp
/*
* And away we go. This doesn't return.
*/
call mi_startup
nop
sir
! NOTREACHED
END(_start)
/*
* void cpu_setregs(struct pcpu *pc)
*/
ENTRY(cpu_setregs)
ldx [%o0 + PC_CURPCB], %o1
/*
* Disable interrupts, normal globals.
*/
wrpr %g0, PSTATE_NORMAL, %pstate
/*
* Normal %g6 points to the current thread's PCB, and %g7 points to
* the per-CPU data structure.
*/
mov %o1, PCB_REG
mov %o0, PCPU_REG
/*
* Switch to alternate globals.
*/
wrpr %g0, PSTATE_ALT, %pstate
/*
* Alternate %g5 points to a per-CPU panic stack, %g6 points to the
* current thread's PCB, and %g7 points to the per-CPU data structure.
*/
mov %o0, ASP_REG
mov %o1, PCB_REG
mov %o0, PCPU_REG
/*
* Switch to interrupt globals.
*/
wrpr %g0, PSTATE_INTR, %pstate
/*
* Interrupt %g7 points to the per-CPU data structure.
*/
mov %o0, PCPU_REG
/*
* Switch to normal globals again.
*/
wrpr %g0, PSTATE_NORMAL, %pstate
/*
* Force trap level 1 and take over the trap table.
*/
SET(tl0_base, %o2, %o1)
wrpr %g0, 1, %tl
wrpr %o1, 0, %tba
/*
* Re-enable interrupts.
*/
wrpr %g0, PSTATE_KERNEL, %pstate
retl
nop
END(cpu_setregs)